-- UIMarketMain
-- Created by chengb Jan/27/2015
-- 商城主界面

require "game/ui/form/hero/UIHeroDetailInfo"
require "game/ui/form/market/UIBuyGoods"
require "game/ui/form/market/UIBuyGem"
require "game/ui/form/group_buy/UIGroupPurchase"
require "game/ui/form/market/UIBuyScrap"
require "game/ui/form/market/UIScrapMarket"
require "game/ui/form/ad/UIOldTv"
require "game/ui/form/market/UISuperiorBonusTip"

UIMarketMain = class("UIMarketMain", function()
    return cc.Layer:create();
end);

function UIMarketMain.create()
    return UIMarketMain.new();
end

-- 商品类别信息
local GOODS_TYPE_INFO;

-- 电视机晃动的时间间隔
local TV_SHAKE_INTERVAL = 5;
local PET_ID = 35;

local SUPERIOR_ID       = 5001;     -- 月卡ID
local GROUP_BUY_ID      = 5003;     -- 团购ID
local GIFT_IDS          = {5002, 5004};  -- 这两个图标商品对应的图标需特殊处理
local TIME_GIFT_ID      = 5007;     -- 限时礼包
local FIRST_RECHARGE_ID = 5006;     -- 首充奖励

-- 拼图迷宫地图的底图
local PUZZLE_DLC_NORMAL_BG = {[1003] = "dlc/bg1003_2", [1004] = "dlc/bg1004_2"};

local limitGiftAlert = {};

-- dlc描述
local dlc_goods_desc = {[1001] = 1, [1003] = 2, [1005] = 3, [1004] = 4};

-- 内部函数声明
local sortByPriority;

-- 构造函数
function UIMarketMain:ctor()
    self:setName("UIMarketMain");

    -- 初始化
    local node = cc.CSLoader:createNode("layout/market/MarketMain.csb");
    self:addChild(node);
    self.node = node;

    self.first = true;

    self.heroTypeList = MarketM.getShowGoodsByType("hero");
    self.dlcTypeList = MarketM.getShowGoodsByType("dlc");

    limitGiftAlert = {
        ["fail"] = getLocStr("take_time_gift_fail"),
        ["over_time"] = getLocStr("take_time_gift_over_time"),
        ["take_already"] = getLocStr("take_time_gift_already"),
    };

    if DungeonM.isInDungeon() and not DungeonM.isPause() then
        -- 迷宫中层级要调高
        self:setLocalZOrder(UIMgr.TOP_MENU_ZORDER + 11);
    end

    GOODS_TYPE_INFO = {
        {["type"] = "hero" ,           ["icon"] = "hero_book",    ["name"] = getLocStr("market_goods_type_name3"), ["title_offset"] = cc.p(-7, -1), ["icon_offset"] = cc.p(0, 0)},    -- 英雄
        {["type"] = "dlc" ,            ["icon"] = "dungeon_book", ["name"] = getLocStr("market_goods_type_name1"), ["title_offset"] = cc.p(-6, -1), ["icon_offset"] = cc.p(-13, 0)},  -- 番外篇
        {["type"] = "resource",        ["icon"] = "resource",     ["name"] = getLocStr("market_goods_type_name2"), ["title_offset"] = cc.p(-7, 5),  ["icon_offset"] = cc.p(-11, 5)},  -- 资源
        {["type"] = "month_card",      ["icon"] = "month_card",   ["name"] = getLocStr("market_goods_type_name7"), ["title_offset"] = cc.p(-4, 5),  ["icon_offset"] = cc.p(-5, 7)},   -- 月卡
        {["type"] = "time_limit_gift", ["icon"] = "time_limit",   ["name"] = getLocStr("market_goods_type_name6"), ["title_offset"] = cc.p(-9, 4), ["icon_offset"]  = cc.p(10, -2)},   -- 限时礼包
        {["type"] = "superior",        ["icon"] = "activity",     ["name"] = getLocStr("market_goods_type_name5"), ["title_offset"] = cc.p(-1, -7), ["icon_offset"] = cc.p(-5, -5)},  -- 豪华礼包
    };

    -- 注册事件处理回调函数
    self:registerEventCallback();

    -- 注册点击事件
    self:registerTouchEvent();

    -- 适配
    -- 注：这里适配必须在redraw之前，因为redraw中会重新设置scrollview的尺寸
    self:resize();

    local scrollview = findChildByName(self.node, "CT/scrollview");
    scrollview.initPosY = scrollview:getPositionY();
    self.scrollview = scrollview;
    self.initHeight = scrollview:getInnerContainerSize().height;

    local BT = findChildByName(self.node, "BT");
    self.oldPos = cc.p(BT:getPosition());

    -- 重绘
    self:redraw();
end

-- 适配
function UIMarketMain:resize()
    local w = AlignM.frameSize.width;
    local h = AlignM.frameSize.height;

    local node = self.node;

    -- bg/mask居中显示并充满整个屏幕
    AlignM.fitToScreen(node, "bg");
    AlignM.fitToScreen(node, "mask");

    -- CT居中并缩放至合适大小
    AlignM.alignToCenter(node, "CT");

    local CT = findChildByName(self.node, "CT");
    local panelBg = findChildByName(self.node, "CT/mask1");
    local CTScale = CT:getScale();
    local w = AlignM.frameSize.width;
    local h = AlignM.frameSize.height;

    panelBg:setScaleX(w / DESIGN_WIDTH / CTScale);
    panelBg:setScaleY(h / DESIGN_HEIGHT / CTScale);

    -- TOP顶部居中并缩放至合适大小
    AlignM.alignToTopCenter(node, "TOP");

    -- BT置于底部并缩放至合适大小
    AlignM.alignToBottomCenter(node, "BT");

    local scale = math.min(w / DESIGN_WIDTH, h / DESIGN_HEIGHT);

    -- 设置scroll的新视口高度
    local scrollview = findChildByName(self.node, "CT/scrollview");
    local scrollViewSize = scrollview:getContentSize();

    local height = (h / scale) - 400;
    scrollview:setContentSize(scrollViewSize.width, height);

    -- 动态设置蒙版的位置
    local scrollMask = findChildByName(self.node, "CT/bottom_mask");
    scrollMask:setPosition(scrollMask:getPositionX(), scrollview:getPositionY() - height);
end

-- 注册点击事件
function UIMarketMain:registerTouchEvent()
    local TOP = findChildByName(self.node, "TOP");
    local BT = findChildByName(self.node, "BT");

    -- 注册返回按钮点击事件
    local btnBack = findChildByName(BT, "btn_back");
    local btnBuyGem = findChildByName(BT, "btn_buy_gem");
    local function onBackClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            AudioM.playFx("button_return");

            if DungeonM.isInDungeon() and
               not DungeonM.isPause() then
                -- 在迷宫中，直接关闭商城
                UIMgr:getCurrentScene():removeFormByName("UIMarketMain");
                return;
            end

            -- 如果是主页，则关闭界面
            if self.pageType == "main" then
                UIMgr.getCurrentScene():removeFormByName("UIMarketMain");
            elseif self.pageType == "scrap" then
                -- 切换到英雄页面
                self:showSubPage("hero", true);
                btnBuyGem:setVisible(true);
            elseif self.pageType == "gift" then
                self:showSubPage("superior", true);
            elseif self.pageType == "group_buy" then
                self:showSubPage("superior", true);
            else
                -- 否则切换至主页
                self:showMainPage();
                btnBuyGem:setVisible(true);
            end
        end
    end
    AddBackEventHandler(self, btnBack, onBackClick);

    -- 注册内购按钮点事件
    local btnBuyGem = findChildByName(BT, "btn_buy_gem");
    local function onBuyGemClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            -- 显示钻石购买界面
            self:showRechargePage(true);

            -- 播放界面音效
            AudioM.playFx("market_buy_btn");
        end
    end
    btnBuyGem:addTouchEventListener(onBuyGemClick);

    -- 电视机图标点击事件
    local tvPanel = findChildByName(TOP, "tv_panel");
    local function onTvClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            -- 打开电视机界面
            AudioM.playFx("market_buy_btn");

            UIMgr.getCurrentScene():removeFormByName("UIOldTv");
            local uiForm = UIOldTv.create();
            UIMgr.getCurrentScene():addForm(uiForm);
        end
    end
    tvPanel:addTouchEventListener(onTvClick);
end

-- 注册事件处理回调函数
function UIMarketMain:registerEventCallback()
    -- 注册团购信息更新的回调
    EventMgr.register("UIMarketMain", event.UPDATE_PURCHASE_PROGRESS, function()
        -- 重绘团购页面
        if self.pageType == "group_buy" then
            self:redrawGroupBuyItem();
        end
    end);

    -- 注册购买商品的事件回调
    EventMgr.register("UIMarketMain", event.BUY_GOODS, function(args)
        if self.pageType ~= "main" and self.curType then
            if self.pageType == "scrap" then
                self:openScrapMarket();
            elseif self.curType then
                if self.curType == "dlc" or self.curType == "hero" then
                    -- 更新下数据
                    self.heroTypeList = MarketM.getShowGoodsByType("hero");
                    self.dlcTypeList = MarketM.getShowGoodsByType("dlc");

                    self:showMainPage();
                elseif self.curType == "recharge" then
                    self:showRechargePage(false);

                    -- 如果购买pt成功，更新pt
                    self:redrawPtTitle(args.goodsId)
                else
                    self:showSubPage(self.curType, false);
                end
            end
        end

        -- 提示玩家购买了商品
        local goodsId = args["goodsId"];

        if MarketM.query(goodsId, "classify") ~= "hero" then
            alert(string.format(getLocStr("market_buy_succ"), MarketM.query(goodsId, "name")));
        end

        -- 播放界面音效
        AudioM.playFx("market_buy_success");

        -- 关闭购买界面
        UIMgr.getCurrentScene():removeFormByName("UIBuyGoods");

        -- 如果时购买了月卡，提示玩家到炼金工坊领取奖励
        if goodsId == SUPERIOR_ID then
            UIMgr.getCurrentScene():removeFormByName("UISuperiorBonusTip");
            local desc = getLocStr("workshop_sign_tip");

            local function callfunc()
                if self.pageType == "main" then
                    self:showMainPage();
                end
            end
            confirm2(CONFIRM_TYPE_OK, getLocStr("workshop_sign"), desc, callfunc);
        end
    end);

    -- 注册获得焦点的回调
    EventMgr.register("UIMarketMain", event.FOCUS_CHANGED, function(para)
        if para["get"] == "UIMarketMain" then
            UIMgr:getCurrentScene().topMenu:show(TOPMENU_FRAME_MONEY, TOPMENU_FRAME_GEM);
        end
    end);

    -- 注册通知广告就绪状态的回调
    EventMgr.register("UIMarketMain", event.AD_READY_STATE, function(args)
        local readyState = args.readyState;
        if readyState then
            if AdM.getRemainAdTimes() <= 0 then
                cclog("今日商城收看广告次数已达上限。");
                return;
            end

            -- 显示广告入口
            self:showAdEntry();
        end
    end);

    -- 注册获得领取礼包回调
    EventMgr.register("UIMarketMain", event.TAKE_GIFTS_BONUS, function(args)
        -- 刷新礼包界面
        local class = self.goodsId;
        local info  = MarketM.query(self.goodsId);
        self:showGiftForm(info.id, info.alias, info.icon, false);
    end);

    -- 注册完成限时礼包事件
    EventMgr.register("UIMarketMain", event.ACHIEVE_TIME_GIFT, function(args)
        -- if self.curType == "superior" then
        --     self:stopAllActions();
        --     self:showSubPage("superior", false);
        -- end
    end);

    -- 注册领取限时礼包结果回调
    EventMgr.register("UIMarketMain", event.TAKE_TIME_GIFT_RESULT, function(args)
        UIMgr.getCurrentScene():removeFormByName("UISuperiorBonusTip");
        local result = args.result;
        if type(result) == "table" then
            -- 通用奖励提示框
            local title = getLocStr("time_limit_gift");
            -- 转换奖励数据
            local bonusList = {};
            for _, bonus in pairs(result) do
                table.insert(bonusList, bonus);
            end

            local function callfunc()
                -- 检查首充
                checkFirstChargeBonus();

                if self.pageType == "main" then
                    self:showMainPage();
                end
            end
            showBonusNotifyForm(title, bonusList, callfunc, nil, nil, nil, nil, nil, {["noSortBonus"] = true});
        elseif type(result) == "string" then
            -- 弹字提示
            if limitGiftAlert[result] then
                alert(limitGiftAlert[result]);
            else
                alert(limitGiftAlert["fail"]);
            end
        end
        if self.curType == "superior" then
            self:stopAllActions();
            self:showSubPage("superior", false);
        end
    end);

    -- 限时礼包数据刷新
    EventMgr.register("UIMarketMain", event.USER_INFO_UPDATED, function(args)
        if args == "limit_time_gift" then
            if self.pageType == "main" then
                self:showMainPage();
            end
        end
    end);

    -- pt支付属性不足打开充值选择页面
    EventMgr.register("UIMarketMain", event.OPEN_PAYMENT_WAY, function(args)
        local function openPaymentWay()
            -- 统一转换成小写再处理
            local countryCode = string.upper(cc.Device:getCountryCode());

            -- 台湾，香港，澳门使用MyCard支付
            local myCardCountry = {"TW","HK","MO"};

            if table.indexOf(myCardCountry, countryCode) ~= -1 then
                require "game/ui/form/market/UIMyCardPay";
                UIMgr:getCurrentScene():removeFormByName("UIMyCardPay");
                local uiForm = UIMyCardPay.create();
                UIMgr:getCurrentScene():addForm(uiForm);
            else
                require "game/ui/form/market/UIPaymentWay";
                UIMgr:getCurrentScene():removeFormByName("UIPaymentWay");
                local uiForm = UIPaymentWay.create();
                UIMgr:getCurrentScene():addForm(uiForm);
            end
        end

        local msg = getLocStr("apk_recharge_tips");
        local okText = getLocStr("btn_text_go");
        confirm2(CONFIRM_TYPE_OK, getLocStr("slime_note"), msg, openPaymentWay, nil, okText)
    end);

    self:registerScriptHandler(function(eventType)
        if eventType == "exit" then
            cclog("UIMarketMain 界面析构清理");
            EventMgr.removeAll("UIMarketMain");

            -- 取消正在充值的标记
            if MarketM.isRecharging() then
                MarketM.setRechargingFlag(false);
            end

            if UIMgr.getCurrentScene().mainMap then
                UIMgr.getCurrentScene().mainMap:show();
            end

            if UIMgr.getCurrentScene().topMenu then
                -- 还原TOP的Zorder
                UIMgr.getCurrentScene().topMenu:setVisible(self.oldVisible);
                UIMgr:getCurrentScene().topMenu:setLocalZOrder(self.oldZOrder);
            end

            UIMgr.tryClearUnusedTextures();
        elseif eventType == "enter" then
            -- 播放界面音效
            AudioM.playFx("market_open");

            if UIMgr.getCurrentScene().mainMap then
                UIMgr.getCurrentScene().mainMap:hide();
            end

            local topMenu = UIMgr.getCurrentScene().topMenu;
            -- 临时提高TOP的Zorder
            self.oldVisible = topMenu:isVisible();
            self.oldZOrder = topMenu:getLocalZOrder();
            UIMgr.getCurrentScene().topMenu:setVisible(true);
            UIMgr:getCurrentScene().topMenu:setLocalZOrder(UIMgr.TOP_MENU_ZORDER + 2);

            if MarketM.isRechargeOpen() then
                -- 尝试向平台获取sku商品价格
                MarketM.tryRequestSkuPrice();
            end

            if AdM.isShowAdInMarket() then
                -- 如果需要显示广告，则查询广告是否准备就绪
                performWithDelay(self, queryAdReadyState, 0.1);
            end

            -- 检查提醒（月卡）
            self:checkReminder();

            -- 检查限时礼包
            local leftTime = GiftM.getLimitGiftLeftTime();
            if leftTime <= 0 then
                -- 请求更新
                local info = ME.user.dbase:query("limit_time_gift") or {};
                if not info then
                    return;
                end

                if not info.gift_info then
                    return;
                end

                if not info.gift_info["end_time"] then
                    return;
                end

                Operation.cmd_update_time_limit_gift_info();
            end
        end
    end);
end

-- 隐藏广告入口
function UIMarketMain:hideAdEntry()
    local tvPanel = findChildByName(self.node, "TOP/tv_panel");
    local tvNode = findChildByName(self.node, "TOP/tv_node");
    tvPanel:setVisible(false);

    if self.tvAnimation then
        local function callback()
            tvNode:setVisible(false);
        end
        self.tvAnimation:play(99, 115, nil, 0.3, callback);
    end
end

-- 显示广告入口
function UIMarketMain:showAdEntry()
    if self.tvAnimation == nil then
        -- 电视机动画尚未创建
        return;
    end

    local tvPanel = findChildByName(self.node, "TOP/tv_panel");
    local tvNode  = findChildByName(self.node, "TOP/tv_node");

    tvNode:stopAllActions();

    local function appear()
        tvPanel:setVisible(true);
        tvNode:setVisible(true);
        local scaleUp = cc.ScaleTo:create(0.1, 1.5);
        local scaleDown = cc.ScaleTo:create(0.1, 0.9);
        local scaleUp2 = cc.ScaleTo:create(0.1, 1.1);
        local scaleDown2 = cc.ScaleTo:create(0.1, 1.0);
        local callfunc = cc.CallFunc:create(function()
            -- 定时播放抖动
            local function shade()
                self.tvAnimation:play(1, 98);
                performWithDelay(self, shade, TV_SHAKE_INTERVAL);
            end
            shade();
        end);
        local delay = cc.DelayTime:create(1);
        tvNode:runAction(cc.Sequence:create(scaleUp, scaleDown, scaleUp2, scaleDown2,
            delay, callfunc));
    end

    performWithDelay(self, appear, 1);
end

-- 初始化电视机动画
function UIMarketMain:initTvAnim()
    -- 默认先隐藏，等接收到广告准备就绪的事件后在显示出来
    local tvPanel = findChildByName(self.node, "TOP/tv_panel");
    local tvNode =  findChildByName(self.node, "TOP/tv_node");
    tvPanel:setVisible(false);
    tvNode:setVisible(false);

    -- 创建电视机动画，初始化停留在第0帧
    local animation = createEffectAnim(1248);
    animation:gotoFrameAndPause(0);
    self.tvAnimation = animation;
    tvNode:removeAllChildren();
    tvNode:addChild(animation);
end

-- 重绘
function UIMarketMain:redraw()
    local node = self.node;

    -- 初始化电视机动画
    self:initTvAnim();

    local btNode = findChildByName(node, "BT");

    -- 设置标题文本
    local titleLabel = findChildByName(node, "TOP/title_node/title")
    titleLabel:setString(getLocStr("mystic_shop"));
    TextStyleM.setArtWordTitleStyle(titleLabel);

    -- 设置返回按钮的文本样式
    local btnBack = findChildByName(btNode, "btn_back");
    TextStyleM.setTextStyle(btnBack, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
    btnBack:setTitleText(getLocStr("btn_text_back"));

    -- 设置充值按钮的文本样式
    local btnBuyGem = findChildByName(btNode, "btn_buy_gem");
    TextStyleM.setTextStyle(btnBuyGem, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
    btnBuyGem:setTitleText(getLocStr("recharge"));

    -- 默认显示商品主页
    self:showMainPage();
end

-- 初始化主页项
function UIMarketMain:initMainItem(child, info)
    local icon = child:getChildByName("icon");
    local nameLabel = findChildByName(child, "title");

    -- 豪华礼包检查可领取数量
    if info.type == "superior" then
        local totalNum = GiftM.calcAllCanTakeBonus() + GroupPurchaseM.getALlCanTakeBonusNum();

        if MarketM.canTakeFirstChargeBonus() then
            totalNum = totalNum + 1;
        end

        local hint = findChildByName(icon, "hint");
        self:checkHint(hint, totalNum);
    end

    -- 微调
    icon:loadTexture(getNewMarketIconPath(info["icon"]));
    icon:setPosition(info["icon_offset"]);

    -- 名称
    -- icon,如果商品售罄，那么显示售罄标识
    if info["sold_out"] == 1 then
        -- 置灰节点
        setGrayMode(icon, true);

        TextStyleM.setTextStyle(nameLabel, TextStyleM.TEXT_SIZE_SMALL, TextStyleM.TEXT_COLOR_GRAY, false, -1);
    else
        if child.type == "time_limit_gift" then
            TextStyleM.setTextStyle(nameLabel, TextStyleM.TEXT_SIZE_MINI, TextStyleM.TEXT_COLOR_GOLD_YELLOW, false, -1);
        else
            TextStyleM.setTextStyle(nameLabel, TextStyleM.TEXT_SIZE_SMALL, TextStyleM.TEXT_COLOR_BROWN_YELLOW, false, -1);
        end
    end

    nameLabel:setString(info["name"]);
    nameLabel:setPosition(cc.pAdd(cc.p(nameLabel:getPosition()), info["title_offset"]));

    -- 限时礼包显示倒计时
    if info["type"] == "time_limit_gift" then
        self:redrawLimitGiftTime(child, info);
    end

    local function onClick(sender, eventType)
        if eventType == ccui.TouchEventType.began then
            icon:runAction(cc.ScaleTo:create(0.1, 0.97));
        elseif eventType == ccui.TouchEventType.canceled then
            icon:runAction(cc.ScaleTo:create(0.1, 1));
        elseif eventType == ccui.TouchEventType.ended then
            icon:runAction(cc.ScaleTo:create(0.1, 1));

            AudioM.playFx("button_click");
            local function callFunc()
                if child.type == "time_limit_gift" then
                    self:timeLimitGiftTip();
                elseif child.type == "month_card" then
                    self:tryBuySuperior(SUPERIOR_ID, 2);
                else
                    -- 显示对应类别的商品
                    self:showSubPage(child.type, true);
                end
            end
            performWithDelay(self, callFunc, 0.1);
        end
    end
    if info["sold_out"] ~= 1 then
        icon:addTouchEventListener(onClick);
    end
end

-- 根据排序优先级排序
function sortByPriority(goods1, goods2)
    if type(goods1) ~= "table" or type(goods2) ~= "table" then
        return false;
    end

    local priority1 = goods1.sort_priority or 0;
    local priority2 = goods2.sort_priority or 0;

    return priority1 < priority2;
end

-- 显示主页
function UIMarketMain:showMainPage()
    local list = self:getMainPageItem();

    local function initFunc(child, info)
        self:initMainItem(child, info);
    end

    self:redrawMainPage(list, getLocStr("mystic_shop"), initFunc);
    self.first = false;
end

-- 初始化二级页面项
function UIMarketMain:initSubItem(child, info)
    child.id = info["id"];
    local goodsId = child.id;

    local doubleImg = findChildByName(child, "hind_node");
    doubleImg:setVisible(false);

    local iconBg = findChildByName(child, "bg_icon");
    iconBg:loadTexture(getNewMarketIconPath("resource/resource_gem"));

    local bg = child:getChildByName("bg");
    bg:loadTexture(getNewMarketIconPath("bg3"));
    local function onClick(sender, eventType)
        if eventType == ccui.TouchEventType.began then
            child:runAction(cc.ScaleTo:create(0.1, 0.97));
        elseif eventType == ccui.TouchEventType.canceled then
            child:runAction(cc.ScaleTo:create(0.1, 1));
        elseif eventType == ccui.TouchEventType.ended then
            child:runAction(cc.ScaleTo:create(0.1, 1));

            -- 如果ID小于0， 显示荣誉碎片购买页
            if goodsId == -1 then
                self:openScrapMarket();
                return;
            end

            if goodsId == -2 then
                self:shouGroupBuy();
            end

            if MarketM.isSoldOut(goodsId) then
                -- 该商品已售完
                alert(string.format(getLocStr("market_goods_sold_out"), MarketM.query(goodsId, "name")));
                AudioM.playFx("market_buy_failed");
                return;
            end

            -- 显示购买界面
            if goodsId ~= -2 then
                self:openBuyForm(goodsId, 1);
            end
        end
    end
    bg:addTouchEventListener(onClick);

    -- 获取名字颜色
    local dbase = info["dbase"];
    local color = dbase and info["dbase"]["title_color"] or "orange";
    if type(color) == "string" then
        if color == "orange" then
            color = TextStyleM.TEXT_COLOR_GOLD_YELLOW;
        elseif color == "green" then
            color = TextStyleM.TEXT_COLOR_LIGHT_GREEN;
        elseif color == "blue" then
            color = TextStyleM.TEXT_COLOR_LIGHT_BLUE;
        else
            color = TextStyleM.TEXT_COLOR_GOLD;
        end
    else
        color = TextStyleM.TEXT_COLOR_GOLD_YELLOW;
    end

    -- 字间距
    local kerning = -1;
    if getLang() == "fr" then
        kerning = -3;
    end

    -- 名字
    local nameLabel = findChildByName(child, "name");
    TextStyleM.setTextStyle(nameLabel, TextStyleM.TEXT_SIZE_MIDDLE, color, true, kerning, nil, nil, nil, nil, true);
    TextStyleM.setShadowStyle(nameLabel, cc.size(-0.3, -2.8), TextStyleM.TEXT_COLOR_YELLOW_BROWN);
    TextStyleM.setOutlineStyle(nameLabel, 1, TextStyleM.TEXT_OUTLINE_COLOR, true);
    nameLabel:setString(info["name"]);

    -- 描述
    local descLabel = findChildByName(child, "desc");
    TextStyleM.setTextStyle(descLabel, TextStyleM.TEXT_SIZE_SMALL2, TextStyleM.TEXT_COLOR_DARK_BROWN, false);

    -- icon
    local icon = findChildByName(child, "icon");
    if info["icon"] ~= "" then
        icon:loadTexture(getNewMarketIconPath(info["icon"]));
    end

    -- TODO: 动态获取每一项的描述，暂时找不到好的方法，先这样判断下
    if goodsId == 2001 or goodsId == 2002 then
        -- 金币
        local desc = string.gsub(info["short_desc"], "{money}", tostring(FormulaM.invoke("CALC_GOODS_BONUS_MONEY", ME.user, info["bonus_args"])));
        applyString(descLabel, desc);

        if goodsId == 2001 then icon:setScale(1.2); icon:setPositionX(icon:getPositionX() - 5); end
    elseif goodsId == 2006 then
        -- 古遗迹碎片
        local desc = string.gsub(info["short_desc"], "{debris}", tostring(FormulaM.invoke("CALC_GOODS_BONUS_DEBRIS", ME.user, info["bonus_args"])));
        applyString(descLabel, desc);
    else
        descLabel:setString(info["short_desc"]);
    end

    -- 显示售价
    local priceImg = findChildByName(child, "price_img");
    priceImg:setVisible(false);
    if goodsId > 0 then
        local value  = table.values(info["price"])[1];
        local attrib  = table.keys(info["price"])[1];

        if attrib == "gem" then
            local priceLabel = findChildByName(child, "price");
            priceLabel:setVisible(true);

            local price = string.format(getLocStr("market_sub_price"), value);
            TextStyleM.setTextStyle(priceLabel, TextStyleM.TEXT_SIZE_SMALL, color, true, kerning, nil, nil, nil, nil, true);
            TextStyleM.setShadowStyle(priceLabel, cc.size(-0.3, -2.8), TextStyleM.TEXT_COLOR_YELLOW_BROWN);
            TextStyleM.setOutlineStyle(priceLabel, 1, TextStyleM.TEXT_OUTLINE_COLOR, true);
            priceLabel:setString(price);
            priceLabel:setPositionY(priceLabel:getPositionY() + 1);

            -- 自适应
            priceLabel:setPositionX(nameLabel:getPositionX() + nameLabel:getVirtualRenderer():getContentSize().width + 10);

            -- 钻石图标
            priceImg:setVisible(true);
            priceImg:setScale(0.8);
            priceImg:setPosition(priceLabel:getPositionX() +
                priceLabel:getVirtualRenderer():getContentSize().width + 20,
                priceLabel:getPositionY() + 2);

            -- 反盖一个括号回去
            local tempLabel = ccui.Text:create();
            child:addChild(tempLabel);
            TextStyleM.setTextStyle(tempLabel, TextStyleM.TEXT_SIZE_SMALL, color, true, kerning, nil, nil, nil, nil, true);
            TextStyleM.setShadowStyle(tempLabel, cc.size(-0.3, -2.8), TextStyleM.TEXT_COLOR_YELLOW_BROWN);
            TextStyleM.setOutlineStyle(tempLabel, 1, TextStyleM.TEXT_OUTLINE_COLOR, true);
            tempLabel:setString(getLocStr("anti_bracket"));
            tempLabel:setPosition(priceLabel:getPositionX() +
                priceLabel:getVirtualRenderer():getContentSize().width +
                priceImg:getVirtualRenderer():getContentSize().width,
                priceLabel:getPositionY());
        end
    elseif goodsId == -1 then
        -- 碎片购买界面
        nameLabel:setString(getLocStr("market_fragment"));
        descLabel:setString(getLocStr("market_fragment_desc"));
        icon:loadTexture(getItemIconPath(2001));
        icon:setScale(0.9);
    end
end

-- 根据类型获取名称
function UIMarketMain:getTypeName(type)
    for _, info in pairs(GOODS_TYPE_INFO) do
        if info.type == type then
            return info.name;
        end
    end
    return "";
end

-- 根据商品类别显示分页控件
function UIMarketMain:showSubPage(type, showEffect)
    local shelf = findChildByName(self.node, "TOP/book_shelf");
    shelf:setVisible(false);

    local scrollview = self.scrollview;
    scrollview:setVisible(true);

    local ctNode = findChildByName(self.node, "CT");
    local selectPanel = findChildByName(ctNode, "select_panel");
    local otherPanel = findChildByName(ctNode, "bottom_panel");
    local mask = findChildByName(ctNode, "mask1");
    mask:setVisible(false);
    selectPanel:setVisible(false);
    otherPanel:setVisible(false);

    local priceNode = findChildByName(self.node, "CT/price_node");
    priceNode:setVisible(false);

    local list = MarketM.getShowGoodsByType(type);
    local scrapList = MarketM.getSellScrapList();

    local scrapInfo = { ["id"] = -1, ["icon"] = "", ["sort_priority"] = 7,};

    -- 冈布奥如果已经被购买过
    if type == "resource" and #scrapList > 0 then
        table.insert(list, scrapInfo);
    end

    -- 根据排序优先级重新排序
    table.sort(list, sortByPriority);

    local function initFunc(child, info, isSelected)
        if type == "superior" then
            self:initSuperiorItem(child, info);
        elseif type == "hero" then
            self:initHeroItem(child, info);
        elseif type == "dlc" then
            self:initDlcItem(child, info, isSelected);
        else
            self:initSubItem(child, info);
        end
    end

    self.curType = type;

    if type == "hero" or type == "dlc" then
        self:showSlidePage("sub", list, self:getTypeName(type), initFunc, showEffect, type);
    else
        self:showPage("sub", list, self:getTypeName(type), initFunc, showEffect, type);
    end

    -- 播放界面音效
    if type == "dlc" then
        AudioM.playFx("market_dlc");
    elseif type == "resource" then
        AudioM.playFx("market_dlc");
    elseif type == "hero" then
        AudioM.playFx("market_hero");
    elseif type == "talent" then
        AudioM.playFx("market_dlc");
    end
end

-- 初始化充值页面项
function UIMarketMain:initRechargeItem(child, info)
    local goodsId = info.id;
    local bg = child:getChildByName("bg");

    local priceImg = findChildByName(child, "price_img");
    priceImg:setVisible(false);

    -- 首次充值双倍提示
    local marketBuyInfo = ME.user.dbase:query("market_buy", {});
    if nil == marketBuyInfo[goodsId] then
        marketBuyInfo[goodsId] = {}
    end
    local buyTimes = marketBuyInfo[goodsId]["buy_times"] or 0;

    local function onClick(sender, eventType)
        if eventType == ccui.TouchEventType.began then
            child:runAction(cc.ScaleTo:create(0.1, 0.97));
        elseif eventType == ccui.TouchEventType.canceled then
            child:runAction(cc.ScaleTo:create(0.1, 1));
        elseif eventType == ccui.TouchEventType.ended then
            child:runAction(cc.ScaleTo:create(0.1, 1));
            if buyTimes < 1 then
                -- 显示购买界面，首次购买显示
                self:openBuyForm(goodsId, 2);
            else
                -- 直接显示系统提示
                self:systemBuyNotify(goodsId, 2);
            end
        end
    end
    bg:addTouchEventListener(onClick);

    -- 获取名字颜色
    local color = TextStyleM.TEXT_COLOR_LIGHT_BLUE;
    if info["alias"] == "recharge6" or
       info["alias"] == "recharge3" or
       info["alias"] == "recharge8" then
        color = TextStyleM.TEXT_COLOR_LIGHT_GREEN;
    end

    -- 获取充值商品的价格
    local price;
    local sku = MarketM.querySku(goodsId);
    if type(sku) ~= 'string' then
        price = string.format("$%.2f", table.values(info["price"])[1]);
    else
        price = MarketM.getPriceBySku(sku);
    end

    local priceLabel = findChildByName(child, "price");
    priceLabel:setVisible(true);
    price = string.format(getLocStr("market_recharge_price"), price);
    TextStyleM.setTextStyle(priceLabel, TextStyleM.TEXT_SIZE_MINI, color, true, -1, nil, nil, nil, nil, true);
    TextStyleM.setShadowStyle(priceLabel, cc.size(-0.3, -2.8), TextStyleM.TEXT_COLOR_YELLOW_BROWN);
    priceLabel:setString(price);
    priceLabel:setPositionY(priceLabel:getPositionY() + 3);

    -- 名字
    local nameLabel = findChildByName(child, "name");
    TextStyleM.setTextStyle(nameLabel, TextStyleM.TEXT_SIZE_SMALL, color, true, -1, nil, nil, nil, nil, true);
    TextStyleM.setShadowStyle(nameLabel, cc.size(-0.3, -2.8), TextStyleM.TEXT_COLOR_YELLOW_BROWN);
    nameLabel:setString(info["name"]);

    -- 价格位置自适应
    priceLabel:setPositionX(nameLabel:getPositionX() + nameLabel:getVirtualRenderer():getContentSize().width + 10);

    -- 描述
    local descLabel = findChildByName(child, "desc");
    TextStyleM.setTextStyle(descLabel, TextStyleM.TEXT_SIZE_MINI, TextStyleM.TEXT_COLOR_DARK_BROWN, false, -1);
    TextStyleM.setShadowStyle(descLabel, cc.size(-0.3, -1.5));

    -- icon
    local icon = findChildByName(child, "icon");
    icon:loadTexture(getUIMarketIconPath(info["icon"]));

    local doubleImg = findChildByName(child, "hind_node");
    local text = findChildByName(doubleImg, "text");
    text:setVisible(false);
    doubleImg:loadTexture(getUIMarketIconPath("double_bonus"));

    if buyTimes < 1 then
        -- 未购买过，显示双倍提示
        doubleImg:setVisible(true);
        doubleImg:setPosition(doubleImg:getPositionX() - 15, doubleImg:getPositionY() - 10);

        applyString(descLabel, info["short_desc"]);

        -- 呼吸效果
        playBubbleAnima(doubleImg, false, 1);
    else
        doubleImg:setVisible(false);

        -- 购买后显示购买之后的描述
        local afterByDesc = info["after_buy_desc"];
        if afterByDesc then
            applyString(descLabel, afterByDesc);
        end
    end
end

-- 显示充值页面
function UIMarketMain:showRechargePage(showEffect)
    -- 关闭商城其他子界面
    UIMgr.getCurrentScene():removeFormByName("UIHeroDetailInfo");
    UIMgr.getCurrentScene():removeFormByName("UIBuyGoods");
    UIMgr:getCurrentScene():removeFormByName("UIGroupPurchase");
    UIMgr.getCurrentScene():removeFormByName("UIBuyScrap");
    UIMgr.getCurrentScene():removeFormByName("UIScrapMarket");

    self.scrollview:setVisible(true);

    local ctNode = findChildByName(self.node, "CT");
    local selectPanel = findChildByName(ctNode, "select_panel");
    local otherPanel = findChildByName(ctNode, "bottom_panel");
    local mask = findChildByName(ctNode, "mask1");
    mask:setVisible(false);
    selectPanel:setVisible(false);
    otherPanel:setVisible(false);

    local btNode = findChildByName(self.node, "BT");
    local priceNode = findChildByName(ctNode, "price_node");
    priceNode:setVisible(false);

    local btnBuyGem = findChildByName(btNode, "btn_buy_gem");
    btnBuyGem:setVisible(false);

    local list = MarketM.getRechargeList();

    local function initFunc(child, info)
        self:initRechargeItem(child, info)
    end

    -- 根据排序优先级重新排序
    table.sort(list, sortByPriority);

    self.curType = "recharge";
    self:showPage("sub", list, getLocStr("recharge"), initFunc, showEffect, "recharge");
end

-- 显示购买界面
function UIMarketMain:openBuyForm(goodsId, priceType)
    if MarketM.query(goodsId, "classify") == "hero" then
        -- 显示英雄界面
        UIMgr.getCurrentScene():removeFormByName("UIHeroDetailInfo");
        local uiBuyHero = UIHeroDetailInfo.create(MarketM.query(goodsId, "bonus")[1][2], "market", goodsId);
        UIMgr.getCurrentScene():addForm(uiBuyHero);
    else
        -- 如果是体力恢复的商品，若体力已满，直接弹提示
        if goodsId == MarketM.getGoodsIdByAlias("buy_life") then
            if true ~= FormulaM.invoke("CAN_BUY_GOODS_LIFE", ME.user, goodsId) then
                alert(getLocStr("cannot_buy_life"));
                return;
            end
        end

        if MarketM.isRecharging() then
            trace("UIMarketMain", "正在充值，请稍后...");
            return;
        end

        local function callback()
            UIMgr.getCurrentScene():removeFormByName("UIBuyGoods");
            local uiBuyGoods = UIBuyGoods.create(goodsId, priceType);
            UIMgr.getCurrentScene():addForm(uiBuyGoods);
        end
        checkIfGuestNeedBind(callback);
    end

    -- 播放界面音效
    AudioM.playFx("market_open_child");
end

-- 系统充值界面
function UIMarketMain:systemBuyNotify(goodsId, priceType)
    -- 获取商品信息
    local goodsInfo = MarketM.getGoodsInfo(goodsId);

    local function buyGem()
        -- 真钱购买
        if priceType ~= 1 then
            -- 如果在手机上，通过sdk购买（pt购买不限手机平台）
            if isAndroidPlatform() or isIosPlatform() or MarketM.isBuyGemByPt() then
                if self.buying == true then
                    return;
                end

                if MarketM.isInlandPayWay() then
                    showInlandPayWay(goodsId);
                else
                    MarketM.buyByRmb(goodsId);
                end

                -- 标记正在购买，避免点太快导致崩溃
                self.buying = true;
                performWithDelay(self, function() self.buying = false; end, 0.5);
            else
                -- 暂未开放
                alert(getLocStr("disable_function"));
            end
        end
    end

    if MarketM.isBuyGemByPt() then
        local title = getLocStr("slime_note");
        local ptPrice = goodsInfo["pt_price"];
        local msg = string.format(getLocStr("buy_gem_by_pt_tip"), ptPrice["pt"], goodsInfo["name"]);

        -- 补偿奖励奖励描述
        if string.match(msg, "{extra_desc}") ~= nil then
            local compensateDesc = MarketM.getCompensateDesc(goodsId);
            msg = string.gsub(msg, "{extra_desc}", compensateDesc);
        end

        confirm2(CONFIRM_TYPE_OK, goodsInfo["name"], msg, buyGem);
    else
        buyGem();
    end
end

-- 显示左右滑动类型的商品页
function UIMarketMain:showSlidePage(pageType, list, title, itemInitFunc, showEffect, subType)
    local scrollview = self.scrollview;

    -- 先清空所有页面
    scrollview:removeAllChildren();
    scrollview:setVisible(false);

    -- 标记类型
    self.pageType = pageType;

    -- 重置充值按钮
    self:resetBtnBuyGem(subType, nil, showEffect);

    -- 设置标题文本
    local titleNode = findChildByName(self.node, "TOP/title_node");
    titleNode:setVisible(true);

    local titleLabel = findChildByName(titleNode, "title");
    titleLabel:setString(title);
    TextStyleM.setArtWordTitleStyle(titleLabel);

    local ctNode = findChildByName(self.node, "CT");
    local selectPanel = findChildByName(ctNode, "select_panel");
    local otherPanel = findChildByName(ctNode, "bottom_panel");
    local mask = findChildByName(ctNode, "mask1");
    mask:setVisible(true);
    selectPanel:removeAllChildren();
    otherPanel:removeAllChildren();
    selectPanel:setVisible(true);
    otherPanel:setVisible(true);

    local function onItemClick(child)
        local goodsId = child.id;

        -- 如果ID小于0， 显示荣誉碎片购买页
        if goodsId == -1 then
            self:openScrapMarket();
            return;
        end

        if goodsId == -2 then
            self:shouGroupBuy();
        end

        if MarketM.isSoldOut(goodsId) then
            -- 该商品已售完
            alert(string.format(getLocStr("market_goods_sold_out"), MarketM.query(goodsId, "name")));
            AudioM.playFx("market_buy_failed");
            return;
        end

        -- 显示购买界面
        if goodsId ~= -2 then
            self:openBuyForm(goodsId, 1);
        end
    end

    -- 如果是迷宫类的话(修改充值成开启)
    if subType == "dlc" then
        local btnOpenDlc = findChildByName(self.node, "BT/btn_open_dlc");
        TextStyleM.setTextStyle(btnOpenDlc, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
        btnOpenDlc:setTitleText(getLocStr("btn_text_open"));
        btnOpenDlc:setVisible(true);

        local btnBuyGem = findChildByName(self.node, "BT/btn_buy_gem");
        btnBuyGem:setVisible(false);
    end

    local priceNode = findChildByName(self.node, "CT/price_node");
    local priceLabel = findChildByName(priceNode, "price_label");
    local priceIcon = findChildByName(priceNode, "price_icon");
    priceNode:setVisible(true);
    local function moveFunc(child, index, isInit)
        local info = subType == "hero" and self.heroTypeList[index] or self.dlcTypeList[index];
        TextStyleM.setTextStyle(priceLabel, TextStyleM.TEXT_SIZE_SMALL, TextStyleM.TEXT_COLOR_ORANGE, true);
        priceLabel:setString(string.format(getLocStr("market_hero_price"), info["price"]["gem"]));
        priceIcon:setPosition(priceLabel:getPositionX() + priceLabel:getVirtualRenderer():getContentSize().width / 2 + 30, priceLabel:getPositionY() + 4);

        local scaleTo1 = cc.ScaleTo:create(0.12, 1.2);
        local scaleTo2 = cc.ScaleTo:create(0.12, 1);
        priceNode:runAction(cc.Sequence:create(scaleTo1, scaleTo2));
    end

    -- 初始化售价
    moveFunc(nil, 1, true);

    local node;
    if subType == "hero" then
        node = cc.CSLoader:createNode("layout/market/HeroBookItem.csb");
    else
        node = cc.CSLoader:createNode("layout/market/DungeonBookItem.csb");
    end

    -- 画左右移动物体
    -- 创建一个鼠标选择滑动的容器
    -- @selectPanel 基础容器
    -- @otherPanel  底部容器
    -- @list        需要绘制的物品列表
    -- @itemWidth   绘制物品的宽度
    -- @itemHeight  绘制物品的高度
    -- @initFunc    绘制单个物品的函数
    createSlidePanel(selectPanel, otherPanel, node, list, 360, 0, itemInitFunc, onItemClick, moveFunc)
end

-- 显示上下滑动商品页
function UIMarketMain:showPage(pageType, list, title, itemInitFunc, showEffect, subType)
    local btnOpenDlc = findChildByName(self.node, "BT/btn_open_dlc");
    btnOpenDlc:setVisible(false);

    local scrollview = self.scrollview;

    -- 先清空所有页面
    scrollview:removeAllChildren();

    local ctNode = findChildByName(self.node, "CT");
    local selectPanel = findChildByName(ctNode, "select_panel");
    local otherPanel = findChildByName(ctNode, "bottom_panel");
    local mask = findChildByName(ctNode, "mask1");
    mask:setVisible(false);
    selectPanel:setVisible(false);
    otherPanel:setVisible(false);

    -- 显示书架节点
    local topNode = findChildByName(self.node, "TOP");
    local shelf = findChildByName(topNode, "book_shelf");
    shelf:setVisible(false);

    -- 标记类型
    self.pageType = pageType;

    -- 重置充值按钮
    self:resetBtnBuyGem(subType, nil, showEffect);

    local offset = cc.p(0, 0);

    if not isFullWidthLang() then
        offset = cc.p(20, 0);

        if title == "Hero" then
            offset = cc.p(12, 0);
        end
    end

    -- 设置标题文本
    local titleNode = findChildByName(topNode, "title_node");
    titleNode:setVisible(true);

    local titleLabel = findChildByName(titleNode, "title");
    titleLabel:setString(title);
    TextStyleM.setArtWordTitleStyle(titleLabel);

    -- 显示子标题
    local subheadLabel = findChildByName(titleNode, "subhead");
    subheadLabel:setVisible(false);
    if "recharge" == subType and MarketM.isBuyGemByPt() then
        subheadLabel:setVisible(true);
        TextStyleM.setTextStyle(subheadLabel, TextStyleM.TEXT_SIZE_MINI, TextStyleM.TEXT_COLOR_ORANGE);
        -- 获得pt点
        local ptAmount = ME.user:queryAttrib("pt") or 0;
        local ptStr = getLocStr("surplus_pt");
        ptStr = string.format(ptStr, ptAmount);
        subheadLabel:setString(ptStr);

        -- 如果有副标题，则滚动容器要下移一点，避免遮挡
        scrollview:setPositionY(scrollview.initPosY - 20);
    end

    -- 加载模板
    local iconNode = cc.CSLoader:createNode("layout/market/RechargeItem.csb");
    local widget = replaceNodeWithWidget(iconNode);

    -- 左边距
    local leftMargin = 25;

    -- 行间距
    local gap = 10;
    local offset = 0;

    -- 单个表项高度
    local widgetHeight = 145;
    if pageType ~= "main" then
        widgetHeight = 110;
        gap = 0;

        offset = -3;

        -- 豪华礼包
        if "superior" == subType then
         --   leftMargin = 0;
            offset = -10;
        elseif "recharge" == subType then
            offset = -10;
        end
    end

    local totalNum = #list;
    self.totalNum = totalNum;

    local startHeight = 0;

    -- 计算总高度
    local totalHeight = totalNum * (widgetHeight + gap);
    if totalHeight < self.initHeight then
        startHeight = 0;
        startHeight = self.initHeight - totalHeight;
    end

    startHeight = startHeight + offset;

    -- 设置内部滚动区域的高度
    scrollview:setInnerContainerSize(cc.size(scrollview:getInnerContainerSize().width,
        math.max(totalHeight, self.initHeight)));

    local bg = findChildByName(widget, "bg");
    local bgHeight = bg:getVirtualRenderer():getContentSize().height/2;
    local bgWidth = bg:getVirtualRenderer():getContentSize().width/2;

    self.items = {};
    local i = 0;
    for j = #list, 1, -1 do
        local info = list[j];
        local child = widget:clone();
        local x = leftMargin;
        local y = startHeight + i * (widgetHeight + gap);
        child:setPositionX(x);
        child:setPositionY(y);

        child:setPositionY(bgHeight + y);
        child:setPositionX(bgWidth + x);

        -- 初始化奖励
        child:setTag(i);
        child.type = info.type;
        itemInitFunc(child, info);

        scrollview:addChild(child);
        i = i + 1;

        table.insert(self.items, child);
    end

    -- 默认滑到最顶端
    scrollToTop(scrollview);

    if showEffect then
        local list = {};
        for j = #self.items, 1, -1 do
            table.insert(list, self.items[j]);
        end

        commonScrollItemFlyIn(list);
    end
end

-- 显示主界面
function UIMarketMain:redrawMainPage(list, title, itemInitFunc)
    self.pageType = "main";

    local ctNode = findChildByName(self.node, "CT");
    local selectPanel = findChildByName(ctNode, "select_panel");
    local otherPanel = findChildByName(ctNode, "bottom_panel");
    local mask = findChildByName(ctNode, "mask1");
    mask:setVisible(false);
    selectPanel:setVisible(false);
    otherPanel:setVisible(false);

    local priceNode = findChildByName(self.node, "CT/price_node");
    priceNode:setVisible(false);

    -- 重置充值按钮
    self:resetBtnBuyGem("main", nil, showEffect);

    -- 隐藏滑动列表
    self.scrollview:setVisible(false);

    local topNode = findChildByName(self.node, "TOP");

    local titleNode = findChildByName(topNode, "title_node");
    titleNode:setVisible(false);

    -- 显示书架节点
    local shelf = findChildByName(topNode, "book_shelf");
    shelf:setVisible(true);

    -- 画标题
    local titleLabel = findChildByName(shelf, "title");
    titleLabel:setString(title);
    TextStyleM.setArtWordTitleStyle(titleLabel);

    -- 加载主页物品模板节点
    local iconNode = cc.CSLoader:createNode("layout/market/MarketMainItem.csb");
    local widget = replaceNodeWithWidget(iconNode);

    self.items = {};
    for i = #list, 1, -1 do
        local info = list[i];
        local child = widget:clone();

        local itemNode = findChildByName(shelf, "item" .. i);
        itemNode:removeAllChildren();

        -- 初始化奖励
        child:setTag(i);
        child:setName("child" .. i);
        child.type = info.type;
        itemInitFunc(child, info);

        itemNode:addChild(child);
        i = i + 1;

        local effectIcon = findChildByName(child, "icon");
        effectIcon:setTag(i);
        table.insert(self.items, effectIcon);
    end

    -- 重新排序
    local effectNodes = {
        self.items[3], self.items[2], self.items[1],
        self.items[4], self.items[5], self.items[6],
    }

    -- 掉落动画
    local bg = findChildByName(self.node, "bg");
    goodsDropEffect(bg, effectNodes, -40, {0.1, 0.3, 0.3, 0.4, 0.4, 0.5});
end

-- 初始化荣誉碎片项
function UIMarketMain:initScrapItem(child, info)
    local preGoodsId = info.pre_goods;
    local preinfo = MarketM.getGoodsInfo(preGoodsId);

    local heroId = preinfo.bonus[1][2];
    local icon = PetM.getDefaultIcon(heroId);
    local iconPath = getHeroIconPath(icon);

    local bg = findChildByName(child, "bg");

    -- 英雄图标
    local iconImg = findChildByName(bg, "icon");
    iconImg:loadTexture(iconPath);

    -- 数量
    local numLabel = findChildByName(bg, "num");
    TextStyleM.setTextStyle(numLabel, TextStyleM.TEXT_SIZE_SMALL, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
    numLabel:setString(tostring(info.bonus[1][3]));

    -- 点击处理
    bg:addTouchEventListener(function(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            local goodsId = info.id;
            if MarketM.isSoldOut(goodsId) then
                -- 该商品已售完
                alert(string.format(getLocStr("market_goods_sold_out"), MarketM.query(goodsId, "name")));
                AudioM.playFx("market_buy_failed");
                return;
            end

            -- 显示购买界面
            self:openBuyScrapForm(goodsId, 1);
         end
    end);
end

-- 显示荣誉碎片页面
function UIMarketMain:showScrapPage(pageType)
    local scrollview = self.scrollview;
    scrollview:removeAllChildren();

    self.pageType = "scrap";
    -- 标记类型
    if true == pageType then
        self.pageType = "main";
    end

    -- 标题
    local titleLabel = findChildByName(self.node, "TOP/title_node/title")
    titleLabel:setString(getLocStr("market_goods_type_name4"));
    TextStyleM.setArtWordTitleStyle(titleLabel);

    -- 获取列表
    local finalList = MarketM:getSellScrapList();
    if #finalList == 0 then
        return;
    end

    local itemNode = cc.CSLoader:createNode("layout/market/ScrapItem.csb");
    local widget = replaceNodeWithWidget(itemNode);

    local numPerRow = 3;

    local leftMargin = 3;

    -- 图标横向间距
    local gap = 30;

    -- 图标纵向间距
    local gap2 = 10;

    -- 图标宽度
    local iconWidth = 177;
    local iconHeight = 171;
    local itemNum = #finalList;

    -- 先计算总高度
    local totalHeight = math.max((math.ceil(itemNum / numPerRow)) * (iconWidth + gap), self.initHeight);

    scrollview:setInnerContainerSize(cc.size(scrollview:getInnerContainerSize().width, totalHeight));

    for i = 1, itemNum do
        local child = widget:clone();
        local x = leftMargin + (((i-1) % numPerRow))*iconWidth + iconWidth/2 + gap;
        local y = totalHeight - math.floor((i-1) / numPerRow) * (iconHeight + gap2) - ( iconHeight / 2 + gap2);
        child:setPositionX(x);
        child:setPositionY(y);

        -- 初始化道具
        self:initScrapItem(child, finalList[i]);
        scrollview:addChild(child);
    end

    -- 播放界面音效
    AudioM.playFx("market_open_child");

    -- 默认滑到最顶端
    scrollview:scrollToTop(0.1, true);
end

-- 底部BT按钮显示
function UIMarketMain:showButtons()
    local btNode = findChildByName(self.node, "BT");
    btNode:setVisible(true);
end

-- 底部BT按钮隐藏
function UIMarketMain:hideButtons()
    local btNode = findChildByName(self.node, "BT");
    btNode:setVisible(false);
end

-- 显示团购奖励页面
function UIMarketMain:shouGroupBuy()
     -- 给服务端发送消息
    Operation.cmd_fetch_group_purchase_progress();
    if UIMgr:getCurrentScene():isOpen("UIGroupPurchase") then
        UIMgr:getCurrentScene():removeFormByName("UIGroupPurchase");
    end

    local uiGroupPurchase = UIGroupPurChase.create();
    UIMgr.getCurrentScene():addForm(uiGroupPurchase);
    AudioM.playFx("market_open_child");
end

-- 显示购买碎片的页面
function UIMarketMain:openBuyScrapForm(goodsId, priceType)
    local function callback()
        UIMgr.getCurrentScene():removeFormByName("UIBuyScrap");
        local uiBuyGoods = UIBuyScrap.create(goodsId, priceType);
        UIMgr.getCurrentScene():addForm(uiBuyGoods);
        AudioM.playFx("market_open_child");
    end
    checkIfGuestNeedBind(callback);
end

-- 显示冈布奥碎片界面
function UIMarketMain:openScrapMarket()
    UIMgr.getCurrentScene():removeFormByName("UIScrapMarket");
    local uiForm = UIScrapMarket.create("MarketShop");
    UIMgr.getCurrentScene():addForm(uiForm);
    AudioM.playFx("market_open_child");
end

-- 隐藏Top
function UIMarketMain:hideMarket()
    local topNode = findChildByName(self.node, "TOP");
    topNode:setVisible(false);

    local btNode = findChildByName(self.node, "BT");
    btNode:setVisible(false);
end

-- 显示Top
function UIMarketMain:showMarket()
    local topNode = findChildByName(self.node, "TOP");
    topNode:setVisible(true);

    local btNode = findChildByName(self.node, "BT");
    btNode:setVisible(true);
end

-- 初始化英雄礼包的选项
function UIMarketMain:initHeroItem(child, index)
    local info = self.heroTypeList[index];
    if not info then return; end

    child.id = info["id"];
    local goodsId = child.id;

    -- 画封面
    local book = findChildByName(child, "book");
    book:loadTexture(getNewMarketIconPath(info["icon"]));

    -- 画封面人物
    local heroIcon = findChildByName(child, "icon");
    heroIcon:loadTexture(getHeroLargeIconPath(info["dbase"]["class_id"]));

    -- 红龙微调一下
    if info["dbase"]["class_id"] == 19 then
        heroIcon:setPositionX(book:getPositionX() - 25);
    else
        heroIcon:setPositionX(book:getPositionX() + 5);
    end

    -- 画描述
    local desc = findChildByName(child, "desc");
    TextStyleM.setTextStyle(desc, TextStyleM.TEXT_SIZE_SMALL2, TextStyleM.TEXT_COLOR_WHITE, true, -1, nil, nil, nil, nil, true);
    TextStyleM.setShadowStyle(desc, cc.size(-0.3, -1.5));
    desc:setString(spliceLocStr("\"", info["short_desc"], "\""));

    -- 画名称
    local name = findChildByName(child, "name");
    TextStyleM.setTextStyle(name, TextStyleM.TEXT_SIZE_SMALL2, TextStyleM.TEXT_COLOR_WHITE, true, -1, nil, nil, nil, nil, true);
    TextStyleM.setShadowStyle(name, cc.size(-0.3, -1.5));

    -- 画星级
    local star = info["dbase"]["star"];
    local str = "";
    for i = 1, star do
        str = spliceLocStr(str, "★");
    end
    name:setString(spliceLocStr(info["name"], " ", str));
end

-- 初始化番外篇选项
function UIMarketMain:initDlcItem(child, index, isSelected)
    local info = self.dlcTypeList[index];
    if not info then return; end

    child.id = info["id"];
    local goodsId = child.id;

    -- 开启对应的迷宫
    if isSelected then
        -- 开启
        local function openDlcClick(sender, eventType)
            if eventType == ccui.TouchEventType.ended then
                if MarketM.isSoldOut(goodsId) then
                    -- 该商品已售完
                    alert(string.format(getLocStr("market_goods_sold_out"), MarketM.query(goodsId, "name")));
                    AudioM.playFx("market_buy_failed");
                    return;
                end

                -- 显示购买界面
                if goodsId ~= -2 then
                    self:openBuyForm(goodsId, 1);
                end
            end
        end

        local btnOpenDlc = findChildByName(self.node, "BT/btn_open_dlc");
        btnOpenDlc:addTouchEventListener(openDlcClick);
    end

    -- 检查拼图类迷宫
    local isNormalType = true;
    local replaceBg = false;        -- 只有拼图迷宫才需要替换
    local dbase = info["dbase"] or {};
    local dungeonId = dbase["key_dungeon"];
    if type(dungeonId) == "number" and DungeonPuzzleM.isPuzzleDungeon(dungeonId) then

        if DungeonPuzzleM.checkPlayDlcPuzzleEffect(dungeonId) or not DungeonPuzzleM.isHaveAllPuzzle(dungeonId) then
            -- 还没有集齐的话，以拼图的模式显示
            isNormalType = false;
        end

        if DungeonPuzzleM.isHaveAllPuzzle(dungeonId) then
            -- 如果拼图集齐了需要显示整张图标，背景图替换掉
            replaceBg = true;
        end
    end

    -- 只有需要拼图的才显示（这边先隐藏）
    local itemsPanel = findChildByName(child, "book_items");
    itemsPanel:setVisible(false);

    -- 画封面
    local book = findChildByName(child, "book");
    book:loadTexture(getNewMarketIconPath(info["icon"]));

    -- 封皮人物
    local heroMask = findChildByName(child, "book_mask");
    heroMask:loadTexture(getNewMarketIconPath(info["dbase"]["mask"]));

    -- 画描述
    local desc = findChildByName(child, "desc");
    TextStyleM.setTextStyle(desc, TextStyleM.TEXT_SIZE_SMALL, TextStyleM.TEXT_COLOR_LIGHT_BLUE, true, -1, nil, nil, nil, nil, true);
    TextStyleM.setShadowStyle(desc, cc.size(-0.3, -1.5));
    desc:setString(info["short_desc"]);

    -- 画名称
    local name = findChildByName(child, "name");
    TextStyleM.setTextStyle(name, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_LIGHT_YELLOW, true, -1, nil, nil, nil, nil, true);
    TextStyleM.setShadowStyle(name, cc.size(-0.3, -1.5));
    name:setString(info["name"]);

    -- 画杂志描述(要用亮黄，只能这么做了= = )
    for i = 1, 4 do
        local bookDesc = findChildByName(child, "book_desc_" .. i);

        local color = (i % 2 == 0) and TextStyleM.TEXT_COLOR_BRIGHT_YELLOW or TextStyleM.TEXT_COLOR_WHITE;
        TextStyleM.setTextStyle(bookDesc, TextStyleM.TEXT_SIZE_TINY, color, false);

        local descIndex = dlc_goods_desc[goodsId];
        local bookDescs = string.format("market_book_desc%d_%d", descIndex, i);

        bookDesc:setString(getLocStr(bookDescs));
    end


    local function itemsIsVisible(flag)
        heroMask:setVisible(flag);
        desc:setVisible(flag);
        name:setVisible(flag);
        for i = 1, 4 do
            local bookDesc2 = findChildByName(child, "book_desc_" .. i);
            bookDesc2:setVisible(flag);
        end
    end

    itemsIsVisible(isNormalType);

    -- 如果是拼图迷宫并且未集齐所有迷宫（初始华的拼图）
    if not isNormalType and not replaceBg then
        self:initPuzzleItem(child, info, dungeonId, isSelected);
    end

    if replaceBg then
        -- 检查是否需要播合成拼图效果
        if isSelected and DungeonPuzzleM.checkPlayDlcPuzzleEffect(dungeonId) then
            local function playGainEffect()
                local function frameEventFunc(frame)
                    if frame.getEvent and frame:getEvent() == "pilor" then
                        local index = frame:getFrameIndex();

                        if index == 5 then
                            book:loadTexture(getNewMarketIconPath(PUZZLE_DLC_NORMAL_BG[dungeonId]));
                            local itemsPanel = findChildByName(child, "book_items");

                            itemsPanel:setVisible(false);

                            itemsIsVisible(true);
                            DungeonPuzzleM.markAsReminded(dungeonId);
                        end
                    end
                end

                local lightNode = findChildByName(child, "light_node");
                playEffect(lightNode, 1341, -320, 490, frameEventFunc);
            end

            itemsIsVisible(false);

            self:initPuzzleItem(child, info, dungeonId, isSelected);

            local uiForm = UIInvisibleForm.create(0.7);
            UIMgr.getCurrentScene():addForm(uiForm);

            performWithDelay(self, playGainEffect, 0.5);
        elseif not DungeonPuzzleM.checkPlayDlcPuzzleEffect(dungeonId) then
            book:loadTexture(getNewMarketIconPath(PUZZLE_DLC_NORMAL_BG[dungeonId]));
        else
            self:initPuzzleItem(child, info, dungeonId, isSelected);
        end
    end
end

-- 初始化拼图项
function UIMarketMain:initPuzzleItem(child, info, dungeonId, isSelected)
    local itemsPanel = findChildByName(child, "book_items");
    itemsPanel:setVisible(true);

    -- 当前迷宫对应的所有拼图
    local allPuzzle = DungeonPuzzleM.getAreaPuzzle(dungeonId);

    -- 检查当前位置(获得迷宫的所有拼图)
    local list = DungeonPuzzleM.getPuzzleList(dungeonId) or {};

    -- 加载模板
    local iconNode = cc.CSLoader:createNode("layout/market/DungeonPuzzleItem.csb");
    local widget = replaceNodeWithWidget(iconNode);

    -- 添加所有的拼图
    -- 这边只创建一次，如果对应位置已经有节点就不管，只要重绘下
    -- 重绘并且更新下对应的函数
    for _, id in pairs(allPuzzle) do
        local pos = DungeonPuzzleM.query(id, "pos");
        local itemNode = findChildByName(itemsPanel, "puzzle_" .. pos);
        if  itemNode == nil then
            itemNode = widget:clone();

            itemNode:setName("puzzle_" .. pos);

            -- 计算下位置
            local x = 110 * ((pos - 1) % 3) + 55;
            local yCoef = math.modf((pos-1)/3);
            local y = 385 - yCoef * 111;

            itemNode:setPosition(x, y);

            itemsPanel:addChild(itemNode);
        end

        local bg = findChildByName(itemNode, "icon");

        local icon = findChildByName(itemNode, "icon");
        if table.indexOf(list, id) ~= -1 then
            local bgFile = DungeonPuzzleM.query(id, "bg");
            bg:loadTexture(getDungeonPuzzleIcon(bgFile));

            local iconFile = DungeonPuzzleM.query(id, "icon");
            icon:loadTexture(getDungeonPuzzleIcon(iconFile));

            bg:setVisible(true);
            icon:setVisible(true);

            if isSelected and DungeonPuzzleM.checkSinglePuzzlePlay(id) then
                local function playGainEffect()
                    local function frameEventFunc(frame)
                        if frame.getEvent and frame:getEvent() == "pilor" then
                            local index = frame:getFrameIndex();

                            if index == 5 then
                                DungeonPuzzleM.markCurPuzzleReminded(id);
                            end
                        end
                    end

                    local lightNode = findChildByName(itemNode, "light_node");
                    playEffect(lightNode, 1345, -276, 204, frameEventFunc);
                end

                performWithDelay(itemNode, playGainEffect, 0.3);
            end

        else
            bg:setVisible(false);
            icon:setVisible(false);
        end

        -- 当前还没有对应的拼图需要提示拼图
        local function showPuzzleItemTip(id)
            -- 点击响应效果（拼图由小到大）
            local scale = cc.ScaleTo:create(0.15, 1.2);

            local puzzlePath = DungeonPuzzleM.query(id, "icon");

            local puzzleIcon = ccui.ImageView:create();
            puzzleIcon:loadTexture(getDungeonPuzzleIcon(puzzlePath));
            puzzleIcon:setPosition(10, 11);
            puzzleIcon:setScale(0.8);
            puzzleIcon:setOpacity(80);

            itemNode:addChild(puzzleIcon);

            local clickCallFunc = cc.CallFunc:create(function()
                if table.indexOf(list, id) ~= -1 then
                    -- 迷宫碎片
                    local itemName = ItemM.query(id, "name");
                    local desc = ItemM.getItemDesc(id, {["bonus_detail"] = true});

                    showActivityTip(itemName, desc);
                else
                    -- 对应的
                    local title = ItemM.query(id, "name") .. "[gray]" .. getLocStr("not_captured") .. "[-]";
                    local desc = ItemM.getItemDesc(id, {["gain_way"] = true});
                    showActivityTip(title, desc);
                end

                itemNode:removeChild(puzzleIcon);
            end);

            puzzleIcon:runAction(cc.Sequence:create(scale, clickCallFunc));
        end

        local puzzlePanel = findChildByName(itemNode, "panel");
        puzzlePanel.classId = id;

        puzzlePanel.notScale = true;

        puzzlePanel.childClickFunc = showPuzzleItemTip;

        -- 点击事件将父节点覆盖掉了，需要与父节点一致反应，滑动效果
        childAddSlideMoveFunc(puzzlePanel);
    end
end

-- 初始化豪华礼包的选项
function UIMarketMain:initSuperiorItem(child, info)
    child.id = info["id"];
    local goodsId = child.id;

    local bg = child:getChildByName("bg");
    bg:loadTexture(getNewMarketIconPath("bg3"));
    local iconBg = findChildByName(child, "bg_icon");
    iconBg:loadTexture(getNewMarketIconPath("gift/mask"));

    local priceImg = findChildByName(child, "price_img");
    priceImg:setVisible(false);

    -- 名字
    local nameLabel = findChildByName(child, "name");

    -- 条目
    local numLabel = findChildByName(child, "price");

    -- icon
    local giftImg = findChildByName(child, "icon");

    local hintNode = findChildByName(child, "hind_node");
    local text = findChildByName(hintNode, "text");
    hintNode:setVisible(false);

    if FIRST_RECHARGE_ID == info["id"] then
        -- 首充
        TextStyleM.setTextStyle(nameLabel, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_ORANGE, true, -1, nil, nil, nil, nil, true);
        nameLabel:setString(info["name"]);

        -- 加载礼物图标
        giftImg:setVisible(true);
        local giftImgPath = getNewMarketIconPath("gift/slime");
        giftImg:loadTexture(giftImgPath);
        giftImg:setScale(1.1);

        -- 描述
        local descLabel = findChildByName(child, "desc");
        TextStyleM.setTextStyle(descLabel, TextStyleM.TEXT_SIZE_SMALL2, TextStyleM.TEXT_COLOR_DARK_BROWN, false, -1);
        applyString(descLabel, info["short_desc"]);

        local isHint = MarketM.canTakeFirstChargeBonus();
        local num = isHint and 1 or 0;
        TextStyleM.setTextStyle(numLabel, TextStyleM.TEXT_SIZE_SMALL, TextStyleM.TEXT_COLOR_ORANGE, true, -1, nil, nil, nil, nil, true);

        TextStyleM.setShadowStyle(nameLabel, cc.size(-0.3, -2.8), TextStyleM.TEXT_COLOR_YELLOW_BROWN);
        TextStyleM.setShadowStyle(numLabel, cc.size(-0.3, -2.8), TextStyleM.TEXT_COLOR_YELLOW_BROWN);
        TextStyleM.setOutlineStyle(nameLabel, 1, TextStyleM.TEXT_OUTLINE_COLOR, true);
        TextStyleM.setOutlineStyle(numLabel, 1, TextStyleM.TEXT_OUTLINE_COLOR, true);
        numLabel:setString(string.format(getLocStr("market_gift_num"), num, 1));
        numLabel:setPositionY(numLabel:getPositionY() + 3);
        numLabel:setPositionX(nameLabel:getPositionX() + nameLabel:getVirtualRenderer():getContentSize().width + 10);

        if isHint then
            local bonusTipImg = findChildByName(child, "bonus_tip");
            bonusTipImg:setVisible(true);
            bonusTipImg:loadTexture(getCornerImg("finish"));
            bonusTipImg:setPositionX(bonusTipImg:getPositionX() - 5);
            playBubbleAnima(bonusTipImg, false, 1);
        end
    else
        TextStyleM.setTextStyle(nameLabel, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true, -1, nil, nil, nil, nil, true);
        nameLabel:setString(info["name"]);

        -- 加载礼物图标
        giftImg:setVisible(true);
        giftImg:loadTexture(getNewMarketIconPath(info["icon"]));

        local descLabel = findChildByName(child, "desc");
        TextStyleM.setTextStyle(descLabel, TextStyleM.TEXT_SIZE_SMALL2, TextStyleM.TEXT_COLOR_DARK_BROWN, false, -1);
        applyString(descLabel, info["short_desc"]);

        -- 显示当前剩余礼包的数量
        TextStyleM.setTextStyle(numLabel, TextStyleM.TEXT_SIZE_SMALL, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true, -1, nil, nil, nil, nil, true);

        TextStyleM.setShadowStyle(nameLabel, cc.size(-0.3, -2.8), TextStyleM.TEXT_COLOR_YELLOW_BROWN);
        TextStyleM.setShadowStyle(numLabel, cc.size(-0.3, -2.8), TextStyleM.TEXT_COLOR_YELLOW_BROWN);
        TextStyleM.setOutlineStyle(nameLabel, 1, TextStyleM.TEXT_OUTLINE_COLOR, true);
        TextStyleM.setOutlineStyle(numLabel, 1, TextStyleM.TEXT_OUTLINE_COLOR, true);

        local num = nil;
        local canGetNum
        if goodsId == GROUP_BUY_ID then
            num = GroupPurchaseM.leftBonusNum();

            -- 计算当前可领取礼包数量
            canGetNum = GroupPurchaseM.getALlCanTakeBonusNum(goodsId);

        else
            if info["alias"] == "boss" then
                num = GiftM.getCurUnlockBossGift();
            elseif info["alias"] == "slime" or info["alias"] == "gem" then
                local list = GiftM.ajustGradeList(goodsId, info["alias"]);
                num = #list;
            else
                num = GiftM.getLeftGift(info["alias"]);
            end

            -- 已领取数量
            canGetNum = GiftM.getHasGetGiftNum(info["alias"]);
        end

        numLabel:setString(string.format(getLocStr("market_gift_num"), canGetNum, num));
        numLabel:setPositionY(numLabel:getPositionY() + 3);
        numLabel:setPositionX(nameLabel:getPositionX() + nameLabel:getVirtualRenderer():getContentSize().width + 10);

        local showNum = GiftM.getCanTakeGiftNum(info["alias"]);
        if showNum > 0 then
            hintNode:setVisible(true);
            text:setVisible(true);
            self:checkHint(hintNode, showNum);
        end
    end

    local function onClick(sender, eventType)
        if eventType == ccui.TouchEventType.began then
            child:runAction(cc.ScaleTo:create(0.1, 0.97));
        elseif eventType == ccui.TouchEventType.canceled then
            child:runAction(cc.ScaleTo:create(0.1, 1));
        elseif eventType == ccui.TouchEventType.ended then
            child:runAction(cc.ScaleTo:create(0.1, 1));

            if goodsId == GROUP_BUY_ID then
                -- 给服务端发送消息
                Operation.cmd_fetch_group_purchase_progress();
                -- 飞入效果标示
                self.flyFlag = true;
                self:showGroupBuy(true);
                return;
            elseif goodsId == FIRST_RECHARGE_ID then
                -- 首冲提示
                self:firstRechargeTip(goodsId);
                return;
            end

            local pageType = info["alias"]
            -- 打开礼包界面
            self:showGiftForm(goodsId, pageType, info.icon, true);
        end
    end
    bg:addTouchEventListener(onClick);
end

-- 限时礼包提示
function UIMarketMain:timeLimitGiftTip()
      -- 限时礼包
    local info = table.deepcopy(GiftM.getLimitTimeGiftInfo());
    if not info or not info["gift_info"] then
        return;
    end

    local title = getLocStr("time_limit_gift");
    local bonusList = info.gift_info["bonus_list"];
    local goodsInfo = MarketM.getGoodsInfo(info.gift_info["good_id"]);
    local goodName = goodsInfo["name"];
    local goodsId = goodsInfo["id"];
    local msg = string.format(getLocStr("time_limit_gift_desc"), goodName);
    local sku = MarketM.querySku(goodsId);
    local price;
    if type(sku) ~= 'string' then
        price = string.format("$%.2f", table.values(goodsInfo["price"])[1]);
    else
        price = MarketM.getPriceBySku(sku);
    end

    local value = FormulaM.invoke("CALC_MARKET_BONUS_VALUE", bonusList, info.gift_info["good_id"]);

    if not GiftM.ifAchieveTimeLimitGift() then
        if not MarketM.isRechargeOpen() then
            -- 充值功能暂未开放
            confirm2(CONFIRM_TYPE_OK, getLocStr("slime_note"), getLocStr("recharge_close_tip"));
            return;
        end

        -- 没完成
        local okText, originalText = MarketM.transformPriceText(price, value);

        local extraPara = {["timeLimitGift"] = true, ["is_taken"] = false, ["original_price"] = originalText, ["gift_id"] = info.gift_info["gift_id"]};
        local function okFunc()
            -- 播放界面音效
            AudioM.playFx("market_buy_btn");
            -- 去除自身界面
            UIMgr.getCurrentScene():removeFormByName("UISuperiorBonusTip");

            if not MarketM.isRechargeOpen() then
                -- 充值功能暂未开放
                alert(getLocStr("disable_function"));
                return;
            end

            -- 直接显示系统提示
            self:systemBuyNotify(info.gift_info["good_id"], 2);
        end
        local uiForm = UISuperiorBonusTip.create(title, msg, value,
            bonusList, okText, okFunc, extraPara);
        UIMgr.getCurrentScene():addForm(uiForm);
        AudioM.playFx("market_dlc");
    elseif not GiftM.takeTimeLimitBonusAlready() then
        -- 发送领取请求
        local function okFunc()
            Operation.cmd_take_time_gift_bonus();
        end

        msg = string.format(getLocStr("time_limit_gift_desc2"), goodName);
        local okText = getLocStr("btn_text_take_gift");
        local extraPara = {["timeLimitGift"] = true, ["is_taken"] = true, ["gift_id"] = info.gift_info["gift_id"]};
        local uiForm = UISuperiorBonusTip.create(title, msg, value,
            bonusList, okText, okFunc, extraPara);
        UIMgr.getCurrentScene():addForm(uiForm);
        AudioM.playFx("market_dlc");
    end

    local btnBuyGem = findChildByName(self.node, "BT/btn_buy_gem");
    if btnBuyGem:isVisible() then
        btnBuyGem:setVisible(false);
    end
end

-- 绘制时间回调
function UIMarketMain:redrawLimitGiftTime(node, info)
    local textLabel = findChildByName(node, "time_text");
    local nameLabel = findChildByName(node, "title");
    local icon = findChildByName(node, "icon");
    textLabel:setVisible(true);

    local function tick()
        -- 限时礼包倒计时
        local leftTime = GiftM.getLimitGiftLeftTime();
        if leftTime <= 0 then
            textLabel:setVisible(false);
            nameLabel:setVisible(false);
            icon:setVisible(false);
            return;
        else
            if info and info["sold_out"] == 1 then
                TextStyleM.setTextStyle(textLabel, TextStyleM.TEXT_SIZE_TINY, TextStyleM.TEXT_COLOR_GRAY, false, 0);
            else
                TextStyleM.setTextStyle(textLabel, TextStyleM.TEXT_SIZE_TINY, TextStyleM.TEXT_COLOR_GOLD_YELLOW, false, 0);
            end

            textLabel:setPositionX(nameLabel:getPositionX());
            icon:setVisible(true);
        end

        local timeText;
        local hour = math.floor(leftTime / 3600);
        local minute = math.floor((leftTime - hour * 3600) / 60);
        local second = math.floor(leftTime % 60);
        timeText = string.format(getLocStr("left_time"), hour, minute, second);
        textLabel:setString(timeText);

        performWithDelay(node, tick, 1);
    end

    tick();
end

-- 首冲提示
function UIMarketMain:firstRechargeTip(goodsId)
    -- 首冲奖励
    local title = getLocStr("recharge_bonus_title");
    local bonusList = FormulaM.invoke("CALC_FIRST_RECHARGE_BONUS_LIST");
    if not MarketM.haveEverRecharged() then
        -- 首充奖励提示
        local msg = getLocStr("first_recharge_tip");
        local value = FormulaM.invoke("CALC_MARKET_BONUS_VALUE", bonusList, goodsId);
        local iconPath = getLargeAttribIconPath(FieldsM.query("gem", "icon"));
        local extraPara = {["valueDesc"] = getLocStr("total_value"), ["valueText"] = value, ["icon"] = iconPath};
        local function okFunc()
            -- 播放界面音效
            AudioM.playFx("market_buy_btn");
            -- 去除自身界面
            UIMgr.getCurrentScene():removeFormByName("UISuperiorBonusTip");
            if not MarketM.isRechargeOpen() then
                -- 充值功能暂未开放
                confirm2(CONFIRM_TYPE_OK, getLocStr("slime_note"), getLocStr("recharge_close_tip"));
                return;
            end

            -- 显示钻石购买界面
            self:showRechargePage(true);
        end
        local uiForm = UISuperiorBonusTip.create(title, msg, nil,
            bonusList, getLocStr("btn_text_charge"), okFunc, extraPara);
        UIMgr.getCurrentScene():addForm(uiForm);
        AudioM.playFx("market_dlc");
    elseif MarketM.canTakeFirstChargeBonus() then
        -- 直接打开领取
        local function okFunc()
            MarketM.takeFirstCharge(bonusList);
            self:showSubPage("superior", true);
        end
        showBonusNotifyForm(title, bonusList, okFunc);
    end
end

-- 尝试购买炼金招牌
function UIMarketMain:tryBuySuperior(goodsId, priceType)
    -- 获取商品信息
    local goodsInfo = MarketM.getGoodsInfo(goodsId);

    local function doBuy()
        -- 如果已经购买了炼金坊招牌，那么直接return
        if SuperiorM.getSuperiorLevel() > 0 then
            return;
        end

        -- 真钱购买
        if priceType ~= 1 then
            -- 如果在手机上，通过sdk购买（pt购买不限手机平台）
            if isAndroidPlatform() or isIosPlatform() or MarketM.isBuyGemByPt() then
                if self.buying == true then
                    return;
                end

                if MarketM.isInlandPayWay() then
                    showInlandPayWay(goodsId);
                else
                    MarketM.buyByRmb(goodsId);
                end

                -- 标记正在购买，避免点太快导致崩溃
                self.buying = true;
                performWithDelay(self, function() self.buying = false; end, 0.5);
            else
                -- 暂未开放
                alert(getLocStr("disable_function"));
            end

            -- 关闭界面
            UIMgr.getCurrentScene():removeFormByName("UISuperiorBonusTip");
            return;
        end

        local ret = MarketM.canBuyGoods(goodsId)
        if true ~= ret or type(ret) == "string" then
            if "sold_out" == ret then
                -- 该商品已售完
                alert(string.format(getLocStr("market_goods_sold_out"), MarketM.query(goodsId, "name")));
            elseif "gem_lack" == ret then
                -- 钻石不足
                showGemLackConfirm();
            elseif type(ret) == "string" then
                -- 有提示语，提示之
                alert(getLocStr(ret));
            else
                -- 其他原因，统一提示失败
                trace("UIMarketMain", "购买失败，原因：" .. tostring(ret))
                alert(getLocStr("market_buy_fail"));
            end

            -- 关闭界面
            UIMgr.getCurrentScene():removeFormByName("UISuperiorBonusTip");
            return;
        end

        -- 购买
        Operation.cmd_buy_goods(goodsId);
    end

    local desc = goodsInfo["confirm"];
    local price = goodsInfo["price"];

    -- 动态显示商品价格
    local goodsId = goodsInfo.id;
    local sku = MarketM.querySku(goodsId);
    if type(sku) ~= 'string' then
        price = string.format("$%.2f", table.values(goodsInfo["price"])[1]);
    else
        price = MarketM.getPriceBySku(sku);
    end

    if string.match(desc, "{currency}") ~= nil then
        desc = string.gsub(desc, "{currency}", tostring(price));
        -- 美元转换
        desc = changeDollerCharacter(desc);
    end

    -- 获取确定按钮显示文本
    local okText = string.format(getLocStr("btn_text_buy_with_price"), tostring(price));
    local bonusList = table.deepcopy(SuperiorM.query(1, "daily_bonus"));
    local dailyBonus = {2, 3};
    -- 招牌直接奖励
    local superiorBonus = FormulaM.invoke("CALC_SUPERIOR_BONUS");
    table.insert(bonusList, 1, superiorBonus);
    local value = FormulaM.invoke("CALC_MARKET_BONUS_VALUE", bonusList, goodsId);
    local uiForm = UISuperiorBonusTip.create(goodsInfo.name, desc, value, bonusList,
       okText, doBuy, {["dailyBonus"] = dailyBonus});
    UIMgr.getCurrentScene():addForm(uiForm);

    local btnBuyGem = findChildByName(self.node, "BT/btn_buy_gem");
    if btnBuyGem:isVisible() then
        btnBuyGem:setVisible(false);
    end

    AudioM.playFx("market_dlc");
end

-- 打开礼物画面
function UIMarketMain:showGiftForm(goodsId, class, iconPath, showEffect)
    local scrollview = self.scrollview;
    scrollview:removeAllChildren();

    self.pageType = "gift";

    self.goodsId = goodsId;

    -- 重置充值按钮
    self:resetBtnBuyGem("gift", class, showEffect);

    -- 标题
    local titleLabel = findChildByName(self.node, "TOP/title_node/title");
    local title = MarketM.query(goodsId, "name");
    titleLabel:setString(title);
    TextStyleM.setArtWordTitleStyle(titleLabel);

    -- 获取列表
    local list ;
    if class == "boss" then
        list = GiftM.getKillBossGift();
    elseif class == "slime" or class == "gem" then
        list = GiftM.ajustGradeList(goodsId, class);
    else
        list = GiftM.query(class);
    end

    if #list == 0 then
        return;
    end

    local itemNode = cc.CSLoader:createNode("layout/market/SubMarketItem.csb");
    local widget = replaceNodeWithWidget(itemNode);

    -- 左边距
    local leftMargin = 20;

    -- 行间距
    local gap = 10;
    local offset = 0;

    -- 单个表项高度
    local widgetHeight = 145;
    if self.pageType ~= "main" then
        widgetHeight = 110;
        gap = 0;

        offset = -3;
    end

    local totalNum = #list;
    self.totalNum = totalNum;

    local startHeight = 0;

    -- 计算总高度
    local totalHeight = totalNum * (widgetHeight + gap);
    if totalHeight < self.initHeight then
        startHeight = self.initHeight - totalHeight;
    end

    startHeight = startHeight + offset;

    -- 设置内部滚动区域的高度
    scrollview:setInnerContainerSize(cc.size(scrollview:getInnerContainerSize().width,
        math.max(totalHeight, self.initHeight)));

    local bg = findChildByName(widget, "bg");
    local bgHeight = bg:getVirtualRenderer():getContentSize().height/2;
    local bgWidth = bg:getVirtualRenderer():getContentSize().width/2;

    self.items = {};
    local i = 0;
    for j = #list, 1, -1 do
        local info = list[j];
        local child = widget:clone();
        local x = leftMargin;
        local y = startHeight + i * (widgetHeight + gap);
        child:setPositionY(bgHeight + y);
        child:setPositionX(bgWidth + x);

        -- 初始化奖励
        child:setTag(i);
        child.type = info.type;
        self:initGiftItem(child, info, iconPath, goodsId);

        scrollview:addChild(child);
        i = i + 1;

        table.insert(self.items, child);
    end

    -- 重头到尾做飞入效果的话可能，直接跳转到当前可领或未领项会出现空白页。
    -- 先找到当前跳转 index。计算前面的页可直接显示。
    if showEffect then
        local list = {};
        if class == "slime" or class == "gem" then
            local id = GiftM.getMaxTakenGrade(class);

            -- 每页的容纳的数量
            local pageAmount = math.floor(self.scrollview:getContentSize().height/widgetHeight);
            local flyAmount = math.min(#self.items - id + pageAmount, #self.items);

            for j = flyAmount, 1, -1 do
                table.insert(list, self.items[j]);
            end
        else
            for j = #self.items, 1, -1 do
                table.insert(list, self.items[j]);
            end
        end

        commonScrollItemFlyIn(list);
    end

    if class == "slime" or class == "gem" then

        self:jumpTo(goodsId, class);
    end
end

-- 初始化礼包项目
function UIMarketMain:initGiftItem(child, info, titleImgPath, goodsId)
    -- 类别， 等级
    local class = info.classify;
    local grade = info.grade;

    local bgNode = findChildByName(child, "bg");

    -- 设置标题
    local titleText = findChildByName(bgNode, "title");
    local titleTextStr;
    local textSize = 1;

    if class == "gem" then
        titleTextStr = getLocStr("market_sub_title_gem");
        textSize = TextStyleM.getTextScale(titleTextStr, 8);
    elseif class == "slime" then
        titleTextStr = getLocStr("market_sub_title_slime");
        textSize = TextStyleM.getTextScale(titleTextStr, 10);
    elseif class == "boss" then
        titleTextStr = getLocStr("market_sub_title_boss");
        textSize = TextStyleM.getTextScale(titleTextStr, 10);
    else
        titleTextStr = getLocStr("market_sub_title");
        textSize = 1;
    end

    TextStyleM.setTextStyle(titleText, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true, -1, nil, nil, nil, nil, true, textSize);
    TextStyleM.setShadowStyle(titleText, cc.size(-0.3, -2.8), TextStyleM.TEXT_COLOR_YELLOW_BROWN);
    TextStyleM.setOutlineStyle(titleText, 1, TextStyleM.TEXT_OUTLINE_COLOR, true);
    titleText:setString(titleTextStr);

    -- 显示需求数量
    local requireNumLabel = findChildByName(bgNode, "require_label");
    requireNumLabel:setVisible(true);
    TextStyleM.setTextStyle(requireNumLabel, TextStyleM.TEXT_SIZE_SMALL, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true, -3, nil, nil, nil, nil, true);
    requireNumLabel:setPositionY(titleText:getPositionY() - 1);
    TextStyleM.setShadowStyle(requireNumLabel, cc.size(-0.3, -2.8), TextStyleM.TEXT_COLOR_YELLOW_BROWN);
    TextStyleM.setOutlineStyle(requireNumLabel, 1, TextStyleM.TEXT_OUTLINE_COLOR, true);

    if class == "boss" then
        local bossRequire = info.require;
        local layer = bossRequire.layer;
        requireNumLabel:setString(tostring(layer) .. "F");
    else
        requireNumLabel:setString(info.require);
    end

    -- 根据类别来判断加载的对象
    local requireImg = findChildByName(bgNode, "require_img");
    requireImg:setVisible(true);
    requireImg:setPositionY(titleText:getPositionY() + 0.5);

    local iconPath = nil;
    if "gem" == class then
        iconPath = getSmallAttribIconPath("cost_score");
    elseif "slime" == class then
        iconPath = getSymbolIconPath("star_large");
        requireImg:setScale(0.9);
    elseif "boss" == class then
        iconPath = getCombatStatIconPath("05");
        requireImg:setScale(0.7);
    end

    requireImg:loadTexture(iconPath);

    -- 绘制奖励项
    local bonusList = GiftM.calcBonus(class, grade);
    local itemNode = cc.CSLoader:createNode("layout/market/SuperiorBonusItem.csb");
    local widget = replaceNodeWithWidget(itemNode);
    for i= 1, #bonusList do
        local bonusItem = widget:clone();
        bonusItem:setName("bonus");

        -- 查找bonus的图片
        local bonusIcon = findChildByName(bonusItem, "icon");
        local bonusIconPath = nil;
        local value = bonusList[i]
        local finalScale = 0.7;

        if value[1] == 1 then
            -- 物品奖励
            bonusIconPath = getItemIconPath(ItemM.query(value[2], "icon"));
        elseif value[1] == 2 then
            -- 属性奖励
            local fieldIconPath = FieldsM.query(value[2], "icon");
            bonusIconPath = getLargeAttribIconPath(fieldIconPath);

            if fieldIconPath == "money" or fieldIconPath == "gem" then
                finalScale = 1;
            end

            if "idle_worker_num" == value[2] then
                bonusIconPath = "images/ui/market/newmarket/gift/worker1.png"
            end

        elseif value[1] == 3 then
            -- 冈布奥奖励
            bonusIconPath = getHeroIconPath(PetM.getDefaultIcon(value[2]));
        elseif value[1] == 6 then
            -- 秘宝
            local classId = tonumber(value[2]);
            local fileName = SkyShipSkillM.query(classId, "icon");
            bonusIconPath = getAirShipSkillIconPath(tostring(fileName));
            name = SkyShipSkillM.query(classId, "name");
        elseif value[1] == 8 then
            -- 机器人
            bonusIconPath = getRobotIconPath(SkyRobotM.query(value[2], "icon"));
            name = SkyRobotM.query(value[2], "name");

        end

        local bg = findChildByName(bonusItem, "bg");
        bg:addTouchEventListener(function(sender, eventType)
            if eventType == ccui.TouchEventType.ended then
                showBonusDesc(value);
             end
        end);
        bonusIcon:loadTexture(bonusIconPath);
        bonusIcon:setScale(finalScale);

        local bonusNumLabel = findChildByName(bonusItem, "num_label");
        TextStyleM.setTextStyle(bonusNumLabel, TextStyleM.TEXT_SIZE_MINI, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true, -3, nil, nil, nil, nil, true);
        TextStyleM.setShadowStyle(bonusNumLabel, cc.size(-0.3, -2.8), TextStyleM.TEXT_COLOR_YELLOW_BROWN);
        TextStyleM.setOutlineStyle(bonusNumLabel, 1, TextStyleM.TEXT_OUTLINE_COLOR, true);

        if value[3] >= 1000 then
            local numText = value[3] / 1000;
            bonusNumLabel:setString(tostring(numText) .. "K");
        else
            bonusNumLabel:setString(value[3]);
        end

        if value[3] == 1 then
            bonusNumLabel:setVisible(false);
        end
        local itemPanel = findChildByName(bgNode, "bonus_" .. (4 - i));
        itemPanel:addChild(bonusItem);
    end

    local titleLabel = findChildByName(bgNode, "title_label");
    -- 根据当前grade奖励领取情况,重绘Item
    if GiftM.beAlreadyTook(class, grade) then
        -- 奖励已领取
        if class == "boss" then
            TextStyleM.setTextStyle(titleLabel, TextStyleM.TEXT_SIZE_SMALL2, TextStyleM.TEXT_COLOR_DARK_BROWN, false, -1);
            local bossRequire = info.require;
            local dungeonName = DungeonAreaM.query(bossRequire.dungeon_id, "name");
            local bossName = MonsterM.query(info.boss_id, "name");
            titleLabel:setString(getLocStr("awards_have_received"));
        else
           TextStyleM.setTextStyle(titleLabel, TextStyleM.TEXT_SIZE_SMALL2, TextStyleM.TEXT_COLOR_DARK_BROWN, false, -1);
           titleLabel:setString(getLocStr("awards_have_received"));
        end

        requireNumLabel:setVisible(false);

        local receivedImg = findChildByName(bgNode, "receive_img");
        receivedImg:setVisible(true);
        receivedImg:setOpacity(100);

        -- 设置bg,奖品为灰色
        self:setGray(child);
    elseif GiftM.canTakeGift(class, grade) then
        -- 奖励可领，未领取
        local progress = GiftM.getProgress(class);
        TextStyleM.setTextStyle(titleLabel, TextStyleM.TEXT_SIZE_SMALL2, TextStyleM.TEXT_COLOR_DARK_BROWN, false, -1);
        if class == "boss" then
            local bossRequire = info.require;
            local dungeonName = DungeonAreaM.query(bossRequire.dungeon_id, "name");

            local dungeonName = DungeonAreaM.query(bossRequire.dungeon_id, "name");
            local bossName = MonsterM.query(info.boss_id, "name");
            titleLabel:setString(string.format(getLocStr("kill_boss_gift"), dungeonName, bossName));
        else
            titleLabel:setString(string.format(getLocStr("can_receive"), progress, info.require));
        end

        local bonusTipImg = findChildByName(bgNode, "bonus_tip");
        bonusTipImg:setVisible(true);
        playBubbleSlightAnima(bonusTipImg, 0.05)
    else
        -- 还不能领取
        local progress = GiftM.getProgress(class);
        TextStyleM.setTextStyle(titleLabel, TextStyleM.TEXT_SIZE_SMALL2, TextStyleM.TEXT_COLOR_GRAY, false, -1);
        if class == "boss" then
            local bossRequire = info.require;
            local dungeonName = DungeonAreaM.query(bossRequire.dungeon_id, "name");

            local dungeonName = DungeonAreaM.query(bossRequire.dungeon_id, "name");
            local bossName = MonsterM.query(info.boss_id, "name");
            titleLabel:setString(string.format(getLocStr("not_kill_boss"), dungeonName, bossName));
        else
            titleLabel:setString(string.format(getLocStr("can_not_receive"), progress, info.require));
        end

        local receivedImg = findChildByName(bgNode, "receive_img");
        receivedImg:setVisible(true);
        receivedImg:setOpacity(100);
    end

end

-- 设置图标和背景为灰色
function UIMarketMain:setGray(child)
    local bg = findChildByName(child, "bg");
    setGrayTransMode(bg, true)

    local requireImg = findChildByName(bg, "require_img");
    setGrayTransMode(requireImg, true);

    requireImg:setVisible(false);

    -- 背景置灰
    local bgIcon = findChildByName(bg, "sub_bg");
    setGrayTransMode(bgIcon, true);

    -- 设置奖品图标为灰色
    for i = 1, 3 do
        local bonusPanel = findChildByName(bg, "bonus_" .. i);
        local item = findChildByName(bonusPanel, "bonus");
        if item ~= nil then
            local iconBg = findChildByName(item, "bg");
            setGrayTransMode(iconBg, true);
            local icon = findChildByName(item, "icon");
            setGrayTransMode(icon, true);

            local numLabel = findChildByName(item, "num_label");
            TextStyleM.setTextStyle(numLabel, TextStyleM.TEXT_SIZE_TINY, TextStyleM.TEXT_COLOR_GRAY2, true, -3);

            numLabel:setVisible(false);
        end
    end
end

-- 显示团购奖励的领取相关的
function UIMarketMain:showGroupBuy(showEffect)
    local scrollview = self.scrollview;
    scrollview:removeAllChildren();

    self.pageType = "group_buy";

    -- 标题
    local titleLabel = findChildByName(self.node, "TOP/title_node/title");
    local title = MarketM.query(GROUP_BUY_ID, "name");
    titleLabel:setString(title);
    TextStyleM.setArtWordTitleStyle(titleLabel);

    -- 获取列表
    local list = GroupPurchaseM.getSpecialGoodsIds();
    if #list == 0 then
        self:showSubPage("superior", true);
        self:resetBtnBuyGem("superior");
        return;
    end

    local heroList = {};
    -- 收集冈布奥的信息
    for _, goodsId in pairs(list) do
        local info = MarketM.getGoodsInfo(goodsId);
        table.insert(heroList, info);
    end

    if not heroList or #heroList == 0 then
        cclog("收集英雄信息失败。");
        return;
    end

    local itemNode = cc.CSLoader:createNode("layout/market/SubMarketItem.csb");
    local widget = replaceNodeWithWidget(itemNode);

    -- 左边距
    local leftMargin = 20;

    -- 行间距
    local gap = 10;
    local offset = 0;

    -- 单个表项高度
    local widgetHeight = 145;
    if self.pageType ~= "main" then
        widgetHeight = 110;
        gap = 0;

        offset = -3;
    end

    local totalNum = #list;
    self.totalNum = totalNum;

    local startHeight = 0;

    -- 计算总高度
    local totalHeight = totalNum * (widgetHeight + gap);
    if totalHeight < self.initHeight then
        startHeight = self.initHeight - totalHeight;
    end

    startHeight = startHeight + offset;

    -- 设置内部滚动区域的高度
    scrollview:setInnerContainerSize(cc.size(scrollview:getInnerContainerSize().width,
        math.max(totalHeight, self.initHeight)));

    self.items = {};
    local i = 0;
    for j = #heroList, 1, -1 do
        local info = heroList[j];
        local child = widget:clone();
        local x = leftMargin;
        local y = startHeight + i * (widgetHeight + gap);
        child:setPositionX(x);
        child:setPositionY(y);

        -- 初始化奖励
        child:setTag(i);
        child.type = info.type;
        self:initGroupBuyItem(child, info);

        scrollview:addChild(child);
        i = i + 1;

        table.insert(self.items, child);
    end

    -- 默认滑到最顶端
    scrollview:scrollToTop(0.1, true);

    if showEffect and self.flyFlag then
        local list = {};
        for j = #self.items, 1, -1 do
            table.insert(list, self.items[j]);
        end

        commonScrollItemFlyIn(list);
        self.flyFlag = false;
        self:resetBtnBuyGem("superior");
    end
end

-- 重绘团购奖励页面
function UIMarketMain:redrawGroupBuyItem()

    local heroList = {};
    -- 收集冈布奥的信息
    -- 获取列表
    local list = GroupPurchaseM.getSpecialGoodsIds();
    for _, goodsId in pairs(list) do
        local info = MarketM.getGoodsInfo(goodsId);
        table.insert(heroList, info);
    end

    --
    local scrollview = self.scrollview;
    local items = scrollview:getChildren();

    local i = 0;
    for j = #heroList, 1, -1 do
        local info = heroList[j];
        local child = scrollview:getChildByTag(i);
        -- 初始化奖励
        self:initGroupBuyItem(child, info);

        i = i + 1;
    end
end

-- 初始化团购项
function UIMarketMain:initGroupBuyItem(child, info)
    local heroId = info.bonus[1][2];

    -- 冈布奥的信息背景
    local groupBuyItemBg = findChildByName(child, "bg/group_buy_bg");
    groupBuyItemBg:setVisible(true);

    local heroIcon = findChildByName(child, "bg/hero_icon");
    heroIcon:setVisible(true);
    heroIcon:loadTexture(getHeroIconPath(PetM.getDefaultIcon(heroId)));

    -- 当前购买冈布奥的人数
    local peopleIcon = findChildByName(child, "bg/require_img");
    peopleIcon:setVisible(true);
    peopleIcon:loadTexture(getGroupPurchaseIcon("people"));

    -- 现有的团购进度
    local hasBuy = GroupPurchaseM.fetchProgress(info.id);
    local progress = 0;
    if hasBuy ~= nil then
        progress = hasBuy.progress;
    end

    -- 数字转换
    local peopleNum = tonumber(progress);
    local numStr = "";
    if peopleNum >= 1000000 then
        local pNum = peopleNum / 1000000;
        local num = string.format("%0.1f", pNum);
        numStr = num .. "M";
    elseif peopleNum >= 1000 then
        local pNum = peopleNum / 1000;
        local num = string.format("%0.1f", pNum);
        numStr = num .. "K";
    else
        numStr = tostring(peopleNum);
    end

    local requireLabel = findChildByName(child, "bg/require_label");
    requireLabel:setVisible(true);
    TextStyleM.setTextStyle(requireLabel, TextStyleM.TEXT_SIZE_MINI, TextStyleM.TEXT_COLOR_ORANGE, true, -3);

    requireLabel:setString(numStr);

    -- 当前状态
    local petList = ME.user:getAllPetIds();
    local titleLabel = findChildByName(child, "bg/title_label");
    titleLabel:setVisible(true);

    local hintNode = findChildByName(child, "bg/hint")
    hintNode:setVisible(false);

    if table.indexOf(petList, heroId) == -1 then
        -- 未购买该冈布奥
        TextStyleM.setTextStyle(titleLabel, TextStyleM.TEXT_SIZE_TINY, TextStyleM.TEXT_COLOR_LIGHT_BLUE, true, -3);
        titleLabel:setString(getLocStr("group_buy_tips"));
    else
        local totalCount = GroupPurchaseM.query(info.id, "max_times");

        -- 已经领取过的奖励等级
        local hasTook = GroupPurchaseM.hasTookLevel(info.id);

        -- 可领奖的次数
        local canTake = GroupPurchaseM.maxBonusLevel(info.id);

        local curCanTake = canTake - hasTook;
        if curCanTake < 1 then
            -- 如果还有下阶奖励可领取
            TextStyleM.setTextStyle(titleLabel, TextStyleM.TEXT_SIZE_TINY, TextStyleM.TEXT_COLOR_LIGHT_GREEN, true, -3);
            if hasTook < totalCount then
                local nextRequire = GroupPurchaseM.getRequire(info.id, hasTook + 1);
                titleLabel:setString(string.format(getLocStr("next_time_bonus"), peopleNum, nextRequire));
            else
                titleLabel:setString("");
            end

        else
            -- 提示当前奖励数量
            TextStyleM.setTextStyle(titleLabel, TextStyleM.TEXT_SIZE_TINY, TextStyleM.TEXT_COLOR_LIGHT_GREEN, true, -3);
            titleLabel:setString(getLocStr("cur_can_take_num"));

            self:checkHint(hintNode, curCanTake);
        end
    end

    -- 注册按钮点击事件
    local bg = findChildByName(child, "bg");
    local function bgOnclick(sender, eventType)
        if eventType == ccui.TouchEventType.began then
            bg:runAction(cc.ScaleTo:create(0.1, 0.97));
        elseif eventType == ccui.TouchEventType.canceled then
            bg:runAction(cc.ScaleTo:create(0.1, 1));
        elseif eventType == ccui.TouchEventType.ended then
            bg:runAction(cc.ScaleTo:create(0.1, 1));
            -- 关闭当前界面
            if UIMgr:getCurrentScene():isOpen("UIGroupBuyInfo") then
                UIMgr:getCurrentScene():removeForm("UIGroupBuyInfo");
            end

            local uiGroupBuyInfo = UIGroupBuyInfo.create(info.id);
            UIMgr.getCurrentScene():addForm(uiGroupBuyInfo);
            AudioM.playFx("button_caption");
        end
    end
    bg:addTouchEventListener(bgOnclick);
end

-- 判断主页商品是否有售罄的
function UIMarketMain:getMainPageItem()
    local list = GOODS_TYPE_INFO;
    local  ret = {};

    for k, value in pairs(list) do
        if value.type == "hero" or value.type == "dlc" then
            -- 判断子选项是否售罄
            local subList = MarketM.getSellGoldsByType(value.type);
            if #subList <= 0 then
                value["sold_out"] = 1;
            end
        elseif value.type == "month_card" then
            -- 判断限时礼包是否已购买
            if SuperiorM.getSuperiorLevel() > 0 then
                value["sold_out"] = 1;
            end
        elseif value.type == "time_limit_gift" then
            local canShow = GiftM.canShowLimitTimeGift();
            if not canShow then
                value["sold_out"] = 1;
            end
        end

        table.insert(ret, value);
    end

    return ret;
end

-- 检查是有可领取奖励
function UIMarketMain:checkHint(hint, para)
    local valLabel = findChildByName(hint, "text");
    TextStyleM.setTextStyle(valLabel, TextStyleM.TEXT_SIZE_SMALL, TextStyleM.TEXT_COLOR_WHITE, true);
    valLabel:getVirtualRenderer():setAdditionalKerning(getLocKerning() -3);

    if type(para) == "number" then
        if para > 0 then
            hint:setVisible(true);
            valLabel:setVisible(true);
            valLabel:setString(tostring(para));
            playBubbleAnima(hint, false, 1);
        else
            hint:setVisible(false);
        end

    elseif type(para) == "boolean" then
        if para then
            hint:setVisible(true);
            hint:loadTexture("images/ui/main/hint2.png", 1);
            valLabel:setVisible(false);
            playBubbleAnima(hint, false, 1);
        else
            hint:setVisible(false);
        end
    end
end

function UIMarketMain:bonusClick(value, bonusItem)
    if value[1] == 1 then
        -- 物品奖励
        -- 点击处理
        local bg = findChildByName(bonusItem, "bg");
        bg:addTouchEventListener(function(sender, eventType)
            if eventType == ccui.TouchEventType.ended then
                AudioM.playFx("workshop_material");
                -- 显示道具详细信息
                local uiItemDesc = UIItemDesc.create(value[2]);
                UIMgr:getCurrentScene():addForm(uiItemDesc);
            end
        end);

    elseif value[1] == 2 then
        -- 属性奖励
    elseif value[1] == 3 then
        -- 冈布奥奖励

        local bg = findChildByName(bonusItem, "bg");
        bg:addTouchEventListener(function(sender, eventType)
            if eventType == ccui.TouchEventType.ended then
                AudioM.playFx("workshop_material");
                -- 显示道具详细信息
                if UIMgr.getCurrentScene():isOpen("UIHeroDetailInfo") then
                    UIMgr.getCurrentScene():removeFormByName("UIHeroDetailInfo");
                end

                local uiHeroInfo = UIHeroDetailInfo.create(value[2]);
                UIMgr.getCurrentScene():addForm(uiHeroInfo);
            end
        end);
    end
end

-- 重置充值按钮
function UIMarketMain:resetBtnBuyGem(pageType, class, btnEffect)
    local BT = findChildByName(self.node, "BT");

    local btnBuyGem = findChildByName(BT, "btn_buy_gem");

    BT:stopAllActions();

    if not self.first and btnEffect ~= false then
        self:btPopUpFromBottom();
    end

    -- 检查当前是否出现
    local hintNode = findChildByName(btnBuyGem, "hint");

    checkBlueBubbleStatus(hintNode, 0);

    if class ~= nil then
        local canTakeAmount = GiftM.getCanTakeGiftNum(class);
        checkBlueBubbleStatus(hintNode, canTakeAmount);
    end

    if pageType == "superior" then
         btnBuyGem:setVisible(false);

    elseif pageType == "gift" then
         -- 礼物界面需调整为领取
         btnBuyGem:setVisible(true);
         local grade = GiftM.getCanTakeGiftGrade(class);
         if grade == -1 then
             btnBuyGem:setBright(false);
             btnBuyGem:setTouchEnabled(false);
         else
             btnBuyGem:setBright(true);
             btnBuyGem:setTouchEnabled(true);
         end

         -- 注册领取按钮
         local function onTakeGift(sender, eventType)

             if eventType == ccui.TouchEventType.ended then
                 -- 先计算奖励，点击完确认后才奖励
                 if GiftM.canTakeGift(class, grade) then
                     -- 奖励
                     local arr = GiftM.calcBonus(class, grade);
                     local function okFunc()
                         GiftM.takeGift(class, grade);
                     end
                     showBonusNotifyForm(getLocStr("market_goods_type_name5"), arr, okFunc);
                 end
             end
         end
         btnBuyGem:addTouchEventListener(onTakeGift);
         TextStyleM.setTextStyle(btnBuyGem, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
         btnBuyGem:setTitleText(getLocStr("take_bonus"));

     elseif pageType == "recharge" then
         btnBuyGem:setVisible(false);
     else
         btnBuyGem:setVisible(true);
         btnBuyGem:setBright(true);
         btnBuyGem:setTouchEnabled(true);

        local function onBuyGemClick(sender, eventType)
            if eventType == ccui.TouchEventType.ended then
                -- 播放界面音效
                AudioM.playFx("market_buy_btn");

                if not MarketM.isRechargeOpen() then
                    -- 充值功能暂未开放
                    confirm2(CONFIRM_TYPE_OK, getLocStr("slime_note"), getLocStr("recharge_close_tip"));
                    return;
                end

                local shelf = findChildByName(self.node, "TOP/book_shelf");
                shelf:setVisible(false);

                -- 显示钻石购买界面
                self:showRechargePage(true);
            end
        end
        btnBuyGem:addTouchEventListener(onBuyGemClick);

        TextStyleM.setTextStyle(btnBuyGem, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
        btnBuyGem:setTitleText(getLocStr("recharge"));
     end
end

-- BT节点一段时间后，从底部往上弹出
function UIMarketMain:btPopUpFromBottom()
    local BT = findChildByName(self.node, "BT");
    if not BT then
        return;
    end

    local oldPos = self.oldPos;
    BT:setPosition(oldPos.x, - 300);
    local delay = cc.DelayTime:create(0.25);
    local moveUp = cc.EaseIn:create(cc.MoveTo:create(0.1, cc.p(oldPos.x, oldPos.y + 5)), 0.3);
    local moveDown = cc.EaseIn:create(cc.MoveTo:create(0.1, cc.p(oldPos.x, oldPos.y - 3)), 0.3);
    local moveUp2 = cc.EaseIn:create(cc.MoveTo:create(0.1, cc.p(oldPos.x, oldPos.y)), 0.3);
    BT:stopAllActions();
    BT:runAction(cc.Sequence:create(delay, moveUp ,moveDown, moveUp2));
end

-- 检查提醒
function UIMarketMain:checkReminder()
    -- 如果月卡购买过且过期则提示
    if SuperiorM.getSuperiorData() and SuperiorM.isOverdue() then
        local desc = getLocStr("superior_reminder");
        confirm2(CONFIRM_TYPE_OK, getLocStr("workshop_sign"), desc);
    end
end

-- 移动中心
function UIMarketMain:jumpTo(goodsId, alias)
    local id = GiftM.getMaxTakenGrade(alias);
    local list = GiftM.ajustGradeList(goodsId, alias);
    local totalCount = #list;

    id = iif(id==nil, 1, id);
    id = id + 2;
    local scrollview = self.scrollview;
    local percent = 100 - id * 100 / totalCount;
    if percent < 0 then
        percent = 0;
    end

    scrollview:jumpToPercentVertical(percent);
end

-- 重绘剩余pt
function UIMarketMain:redrawPtTitle(goodsId)
    if self.curType ~= "recharge" then
        return;
    end

    local subheadLabel = findChildByName(self.node, "TOP/title_node/subhead");
    if subheadLabel:isVisible() and MarketM.isPtRechargeGoods(goodsId) then
        local ptAmount = ME.user:queryAttrib("pt") or 0;
        local ptStr = getLocStr("surplus_pt");
        ptStr = string.format(ptStr, ptAmount);
        subheadLabel:setString(ptStr);
    end
end